本文的項目是官網生成,項目名稱為XX,WEB為MVC,以Users權限模塊為例解說文章。
1.定義PermissionNames
PermissionNames是一個靜態類,它在/XX.Core/Authorization之下
public const string Pages_Users = "Pages.Users";
// 子權限名稱
// public const string Pages_Users_Create = "Pages.Users.Create";
2.添加權限控制
XXAuthorizationProvider.cs,修改SetPermissions方法
public override void SetPermissions(IPermissionDefinitionContext context) { //Common permissions var pages = context.GetPermissionOrNull(PermissionNames.Pages); if (pages == null) { pages = context.CreatePermission(PermissionNames.Pages, L("Pages")); } var users = pages.CreateChildPermission(PermissionNames.Pages_Users, L("Users"));//這里是自定義的權限 //users.CreateChildPermission(PermissionNames.Pages_Users_Create, L("Users_Create"));//這里是自定義的子權限
}
3.添加菜單權限
在web項目下的App_Start中有一個XXNavigationProvider類,它在XXWebModule類的PreInitialize配置
在XXNavigationProvider類的SetNavigation方法中進行添加菜單,且控制配置權限
context.Manager.MainMenu .AddItem( new MenuItemDefinition( "Home", L("HomePage"), url: "", icon: "fa fa-home", requiresAuthentication: true ) ).AddItem( new MenuItemDefinition( "Tenants", L("Tenants"), url: "Tenants", icon: "fa fa-globe", requiredPermissionName: PermissionNames.Pages_Tenants ) ).AddItem( new MenuItemDefinition( "Users", L("Users"), url: "Users", icon: "fa fa-users", requiredPermissionName: PermissionNames.Pages_Users //這是自定義的權限 ) ).AddItem( new MenuItemDefinition( "About", L("About"), url: "About", icon: "fa fa-info" ) ); }
4.展示菜單
在Layout控制器中,使用局部視圖TopMenu進行展示,到這里已經完成
@using Abp.Collections.Extensions @using Zmcor.Web.Views @model Zmcor.Web.Models.Layout.TopMenuViewModel @{ var calculateMenuUrl = new Func<string, string>((url) => { if (string.IsNullOrEmpty(url)) { return ApplicationPath; } if (UrlChecker.IsRooted(url)) { return url; } return ApplicationPath + url; }); } @foreach (var menuItem in Model.MainMenu.Items) { <li class="@(Model.ActiveMenuItemName == menuItem.Name ? "active" : "")"> @if (menuItem.Items.IsNullOrEmpty()) { <a href="@calculateMenuUrl(menuItem.Url)"> @if (!string.IsNullOrWhiteSpace(menuItem.Icon)) { <i class="@menuItem.Icon"></i> } @menuItem.DisplayName </a> } else { <a href="" data-toggle="dropdown"> @if (!string.IsNullOrWhiteSpace(menuItem.Icon)) { <i class="@menuItem.Icon"></i> } @menuItem.DisplayName </a> <ul class="dropdown-menu"> @foreach (var subMenuItem in menuItem.Items) { <li> <a href="@calculateMenuUrl(subMenuItem.Url)"> @if (!string.IsNullOrWhiteSpace(subMenuItem.Icon)) { <i class="@subMenuItem.Icon"></i> } @subMenuItem.DisplayName </a> </li> } </ul> } </li> }
5.角色和權限的關聯
為用戶添加角色
在UserAppService注入UserManager
private readonly UserManager _userManager;
設置角色代碼
/// <summary> /// 設置用戶角色 /// </summary> /// <returns></returns> public async Task SetUserRole(long currentUserId, long userId, string[] roleName) { //權限判斷... var user = _userRepository.FirstOrDefault(s => s.Id == userId); await _userManager.SetRoles(user, roleName); }
在abp中,默認有Admin角色,如果需要創建自己的角色,如下
var myRole = new Role(null,"roleName", "我的角色名稱"); await _roleManager.CreateAsync(myRole);
為角色分配權限
控制器
//視圖顯示
[HttpGet] public async Task<ActionResult> SetRoleMenu(int Id) { var role = _roleAppService.GetRolesById(Id); var myPermissions = await _roleAppService.GetGrantedPermissionsAsync(Id);//數據庫中角色對應的權限 ViewBag.MyPermissions = myPermissions; var rolePermissions = _roleAppService.GetRolePermissionsForManage(); var dictList = new Dictionary<string, string>(); foreach (var item in rolePermissions) { dictList.Add(item.Name, item.DisplayName.ToString().Split(' ')[1].Trim(',')); } ViewBag.RoleList = dictList;//步驟2所定義的權限 return View(role); }
//提交
[HttpPost] public async Task<JsonNetResult> SetRoleMenu(int Id, string PermissionNames) { try { PermissionNames = Request.Form["PermissionNames"]; if (string.IsNullOrWhiteSpace(PermissionNames)) { return new JsonNetErrorResult("請至少選擇一個角色!"); } var roleNames = PermissionNames.Split(',').ToList(); var input = new UpdateRolePermissionsInput() { RoleId = Id, GrantedPermissionNames = roleNames }; var userInfo = GetCurrentUserInfo(); await _roleAppService.UpdateRolePermissions(userInfo.UserId,input); return new JsonNetSuccessResult(); } catch (Exception ex) { return new JsonNetErrorResult("更新出錯" + ex.Message); } }
應用層
public async Task<List<string>> GetGrantedPermissionsAsync(int roleId) { List<string> grantedList = new List<string>(); var grantedPermissions = await _roleManager.GetGrantedPermissionsAsync(roleId); foreach (var item in grantedPermissions) { grantedList.Add(item.Name); } return grantedList; } public List<Permission> GetRolePermissionsForManage() { var grantedPermissions = _permissionManager .GetAllPermissions() .Where(s => s.Name.Contains("Pages.")) .ToList(); return grantedPermissions; }
public async Task UpdateRolePermissions(long userId, UpdateRolePermissionsInput input) { var userAndRole = _userRepository.GetUserAndRolesById(userId); if (userAndRole == null || userAndRole.IsAdmin())) { throw new UserFriendlyException("您無權限進行該操作"); } var role = await _roleManager.GetRoleByIdAsync(input.RoleId); // 如果有子權限,只要添加父權限,會自動添加子權限 //var grantedPermission = _permissionManager // .GetAllPermissions() // .Where(p => input.GrantedPermissionNames.Any(s=> p.Name.Contains(s))) // .ToList(); var grantedPermissions = _permissionManager .GetAllPermissions() .Where(p => input.GrantedPermissionNames.Contains(p.Name)) .ToList(); await _roleManager.SetGrantedPermissionsAsync(role, grantedPermissions); }
IPermissionManager使用_permissionManager.GetAllPermissions() 可以獲取到在步驟2所添加的權限
獲取當前角色的權限:RoleManager => GetGrantedPermissionsAsync(roleId)
獲取所有權限:IPermissionManager=> GetAllPermissions()
更新權限:RoleAppService=> UpdateRolePermissions(UpdateRolePermissionsInput input)
input.GrantedPermissionNames為需授權的權限列表
擴展:授權驗證
控制器授權
[AbpMvcAuthorize(PermissionNames.Pages_Users)] public class UsersController : XXControllerBase
Action授權
[AbpMvcAuthorize(PermissionNames.Companys)] [HttpGet] public async Task<ActionResult> Main() { return View(); }
應用層的授權
[AbpAuthorize(PermissionNames.Pages_Users)] public class UserAppService : ZmcorAppServiceBase, IUserAppService
總結:角色權限這個模塊,整體使用的還是比較簡單、暢通的,注意還需要配置相關的本地化語言文件。如果存在比較復雜的角色和權限,還需要經過一定的設計才能獲得良好的體驗