ABP Zero 导航菜单之角色权限
本文的项目是官网生成,项目名称为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
总结:角色权限这个模块,整体使用的还是比较简单、畅通的,注意还需要配置相关的本地化语言文件。如果存在比较复杂的角色和权限,还需要经过一定的设计才能获得良好的体验