ABP Zero 导航菜单之角色权限

简介: 本文的项目是官网生成,项目名称为XX,WEB为MVC,以Users权限模块为例解说文章。 1.定义PermissionNames PermissionNames是一个静态类,它在/XX.Core/Authorization之下 public const string Pages_Users = "Pages.

本文的项目是官网生成,项目名称为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

 

总结:角色权限这个模块,整体使用的还是比较简单、畅通的,注意还需要配置相关的本地化语言文件。如果存在比较复杂的角色和权限,还需要经过一定的设计才能获得良好的体验

 

相关文章
|
消息中间件 Java API
面试官:如何实现链式调用?
面试官:如何实现链式调用?
663 0
|
安全 Java 数据库
【SpringSecurity】Spring Security 和Shiro对比
【SpringSecurity】Spring Security 和Shiro对比
1249 0
|
测试技术 持续交付 开发者
使用Docker构建CI/CD流程:从理论到实践
【8月更文挑战第2天】使用Docker构建CI/CD流程,可以显著提高软件开发的效率和质量。通过容器化技术,开发者可以确保环境的一致性,快速部署和测试应用,并减少人为错误。结合合适的CI/CD工具和最佳实践,可以进一步加速软件交付过程,提高用户满意度。希望本文能为开发者在构建基于Docker的CI/CD流程时提供有价值的参考。
|
数据采集 存储 算法
「AIGC算法」图搜索算法详解
本文探讨了图搜索算法,包括遍历和最短路径搜索。DFS和BFS是遍历算法,前者使用栈深入搜索,后者用队列逐层遍历。Dijkstra、Bellman-Ford、A*、Floyd-Warshall和Johnson算法则解决最短路径问题。文中还给出了DFS的Python实现示例。这些算法在路径规划、网络分析等领域有重要应用。
787 0
|
安全 网络安全 Windows
Serv-U无法开启后台模式,如何处理?
Serv-U无法开启后台模式,如何处理?
321 14
|
机器学习/深度学习 算法
【2023高教社杯】B题 多波束测线问题 问题分析、数学模型及参考文献
本文介绍了2023年高教社杯数学建模竞赛B题,聚焦于多波束测深系统的覆盖宽度和重叠率问题,包括问题分析、数学模型构建和参考文献,并针对不同场景下的测线设计提出了解决方案。
431 0
【2023高教社杯】B题 多波束测线问题 问题分析、数学模型及参考文献
|
缓存 JavaScript 前端开发
Vue3的魔法:深度解析Computed和Watch原理
【4月更文挑战第18天】
796 1
|
开发框架 移动开发 前端开发
UniApp响应式布局
UniApp 是一款基于 Vue.js 开发的跨平台应用开发框架,可以同时构建 iOS、Android、H5 等多个平台的应用。在 UniApp 中,单位(Unit)是一个非常重要的概念,它决定了应用在不同设备上的布局和样式,要适应不同设备尺寸和屏幕方向的布局是一项艰巨的任务。UniApp 提供了多种方式来实现响应式布局。通过使用 Flex 布局、媒体查询、自适应单位和条件渲染,我们可以根据不同的屏幕尺寸和方向创建出适应性强的布局,从而提供更好的用户体验。
1120 1
|
域名解析 负载均衡 网络协议
一文搞懂常用的网络概念:域名、动态IP、DNS、DDNS(上)
一文搞懂常用的网络概念:域名、动态IP、DNS、DDNS(上)
 一文搞懂常用的网络概念:域名、动态IP、DNS、DDNS(上)
|
前端开发