1.Framework.Core》Authorization》PermissionNames.cs 这里新增权限项

namespace Framework.Authorization
{
    public static class PermissionNames
    {
        public const string Pages_Tenants = "Pages.Tenants";
        public const string Pages_Users = "Pages.Users";
        public const string Pages_Roles = "Pages.Roles";

        /// <summary>
        /// 产品-浏览
        /// </summary>
        public const string Pages_Products = "Pages.Products";
        /// <summary>
        /// 产品-编辑
        /// </summary>
        public const string Pages_Products_Edit = "Pages.Products.Edit";
        /// <summary>
        /// 产品-删除
        /// </summary>
        public const string Pages_Products_Delete = "Pages.Products.Delete";
    }
}

2.Framework.Core》Authorization》FrameworkAuthorizationProvider.cs 这里创建权限,这样在页面中添加角色的时候才能显示出来

using Abp.Authorization;
using Abp.Localization;
using Abp.MultiTenancy;

namespace Framework.Authorization
{
    public class FrameworkAuthorizationProvider : AuthorizationProvider
    {
        public override void SetPermissions(IPermissionDefinitionContext context)
        {
            context.CreatePermission(PermissionNames.Pages_Users, L("Users"));
            context.CreatePermission(PermissionNames.Pages_Roles, L("Roles"));
            context.CreatePermission(PermissionNames.Pages_Tenants, L("Tenants"), multiTenancySides: MultiTenancySides.Host);

            #region 创建权限
            var per = context.CreatePermission(PermissionNames.Pages_Products, L("Products"));
            per.CreateChildPermission(PermissionNames.Pages_Products_Edit, L("EditProducts"));
            per.CreateChildPermission(PermissionNames.Pages_Products_Delete, L("DeleteProducts"));
            #endregion

        }

        private static ILocalizableString L(string name)
        {
            return new LocalizableString(name, FrameworkConsts.LocalizationSourceName);
        }
    }
}

3.其中 Products、EditProducts、DeleteProducts 需要配置本地语言包文件:Framework.Core》Localization》Source》Framework-zh-CN.xml 这是中文的。

        <!-- 自定义 -->
        <text name="Roles" value="角色" />
        <text name="Products" value="商品" />
        <text name="EditProducts" value="编辑商品" />
        <text name="DeleteProducts" value="删除商品" />    

4.左侧菜单 Framework.Web》App_Start》FrameworkNavigationProvider.cs

requiresAuthentication: true 需要登录;requiredPermissionName: PermissionNames.Pages_Products 需要权限

注册菜单在:Framework.Web》App_Start》FrameworkWebModule.cs 的 public override void PreInitialize(){...}里

5.配置Action需要授权,在Action上面加上特性:[AbpAuthorize(PermissionNames.Pages_Products_Delete)]
或者在Action里使用 PermissionChecker,
PermissionChecker.IsGranted(PermissionNames.Pages_Products_Delete) 返回true或者false,
PermissionChecker.Authorize(PermissionNames.Pages_Products_Delete) 如果没有授权,会抛出异常。
在Controller上使用[AbpMvcAuthorize],在AppService上面使用[AbpAuthorize],访问必须先登录;不需要登录[DisableAuditing]。

using Abp.Application.Services;
using Abp.Application.Services.Dto;
using Abp.Auditing;
using Abp.Domain.Repositories;
using Abp.Linq.Expressions;
using Abp.Linq.Extensions;
using Abp.ObjectMapping;
using Abp.UI;
using Framework.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using System.Linq.Dynamic.Core;
using Abp.Authorization;
using Abp.Events.Bus;
using Framework.Events;
using Framework.Products;
using Framework.Products.Dto;

namespace Framework.Products
{
    [AbpAuthorize]
    public class ProductAppService : AsyncCrudAppService<Product, ProductInputDto, long, PagedResultRequestDto, ProductInputDto, ProductInputDto>, IProductAppService
    {
        private readonly IRepository<Product, long> _productRepository;
        private readonly IObjectMapper _objectMapper;

        public IEventBus EventBus { get; set; }

        public ProductAppService(IRepository<Product, long> repository,
            IObjectMapper objectMapper
            ) : base(repository)
        {
            _objectMapper = objectMapper;
            _productRepository = repository;
            EventBus = NullEventBus.Instance;
        }

        [DisableAuditing]
        public async Task<PagedResultDto<ProductInputDto>> GetAllByNameAsync(PagedResultByNameDto input)
        {
            CheckGetAllPermission();
            IQueryable<Product> query = CreateGetAllFilteredQuery(input);
            int totalCount = await AsyncQueryableExecuter.CountAsync(query);
            query = ApplySorting(query, input);
            query = ApplyPaging(query, input);
            var res = new PagedResultDto<ProductInputDto>(totalCount, (await AsyncQueryableExecuter.ToListAsync(query)).Select(MapToEntityDto).ToList());
            return res;
        }
        protected IQueryable<Product> CreateGetAllFilteredQuery(PagedResultByNameDto input)
        {
            Expression<Func<Product, bool>> whereFilter = w => true;
            if (!string.IsNullOrEmpty(input.NameOrCode))
            {
                whereFilter = whereFilter.And(w => w.Name.Contains(input.NameOrCode));
            }
            return Repository.GetAll().Where(whereFilter);
        }
    }
}

左侧菜单示例:

using Abp.Application.Navigation;
using Abp.Authorization;
using Abp.Localization;
using Framework.Authorization;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Framework.Web.App_Start
{
    public class FrameworkVueNavigationProvider : NavigationProvider
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public override void SetNavigation(INavigationProviderContext context)
        {
            Welcome(context);
            Product(context);
            SystemNav(context);
        }
        /// <summary>
        ///欢迎使用
        /// </summary>
        /// <param name="context"></param>
        private void Welcome(INavigationProviderContext context)
        {
            var welcome = GetMenuItemDefinition(
                       name: "",
                       localizableName: "Menu.Welcome",
                       path: "/",
                       isAuth: false,
                       hasMeta: false,
                       redirect: "/welcome",
                       hasTitle: false
                   );

            var welcomeChild = GetMenuItemDefinition(
                       name: "Welcome",
                       localizableName: "Menu.Welcome",
                       icon: "list",
                       path: "welcome",
                       isAuth: false,
                       hasMeta: true,
                       componet: "'@/views/welcome/index'",
                       affix: true
                   );
            welcome.AddItem(welcomeChild);
            context.Manager.MainMenu.AddItem(welcome);
        }

        /// <summary>
        /// 产品管理
        /// </summary>
        /// <param name="context"></param>
        private void Product(INavigationProviderContext context)
        {
            var product = GetMenuItemDefinition(
                       name: "",
                       localizableName: "Menu.Products",
                       path: "/product",//一级路径
                       isAuth: false,
                       hasMeta: false,
                       hasTitle: false
                   );

            var productChild1 = GetMenuItemDefinition(
                       name: "Products",//名称
                       localizableName: "Menu.Products",//多语言配置key
                       icon: "list",//icon图标
                       path: "index",//二级路径:/product/index
                       isAuth: false,
                       hasMeta: true,//显示tab标签名称
                       componet: "'@/views/product/index'",//二级路径对应的视图
                       affix: false//设置tab可以关闭
                   );
            var productChild2 = GetMenuItemDefinition(
                      name: "ProductsEdit",
                      localizableName: "Menu.ProductsEdit",
                      icon: "list",
                      path: "edit",//二级路径:/product/edit
                      isAuth: false,
                      hasMeta: true,
                      componet: "'@/views/product/edit'",//二级路径对应的视图
                      affix: false,//设置tab可以关闭
                      hasTitle: true,
                      isHidden: true
                  );
            product.AddItem(productChild1);
            product.AddItem(productChild2);
            context.Manager.MainMenu.AddItem(product);
        }

        /// <summary>
        /// 系统管理
        /// </summary>
        /// <param name="context"></param>
        private void SystemNav(INavigationProviderContext context)
        {
            var systemRoot = GetMenuItemDefinition(
                      name: "",
                      localizableName: "Menu.Systems",
                      path: "/system",
                      icon: "example",
                      isAuth: true,
                      hasMeta: true,
                       hasTitle: true,
                        permissionDependency: new SimplePermissionDependency(PermissionNames.Pages_Systems)
                  );

            var user = GetMenuItemDefinition(
                       name: "user",
                       localizableName: "Menu.Users",
                       icon: "list",
                       path: "user",
                       isAuth: true,
                       hasMeta: true,
                       componet: "'@/views/system/user'",
                        permissionDependency: new SimplePermissionDependency(PermissionNames.Pages_Systems_Users)
                   );
            systemRoot.AddItem(user);

            var role = GetMenuItemDefinition(
                       name: "role",
                       localizableName: "Menu.Roles",
                       icon: "list",
                       path: "role",
                       isAuth: true,
                       hasMeta: true,
                       componet: "'@/views/system/role'",
                        permissionDependency: new SimplePermissionDependency(PermissionNames.Pages_Systems_Roles)
                   );
            systemRoot.AddItem(role);

            var organizationunit = GetMenuItemDefinition(
                       name: "organizationunit",
                       localizableName: "Menu.OrgUnits",
                       icon: "list",
                       path: "organizationunit",
                       isAuth: true,
                       hasMeta: true,
                       componet: "'@/views/system/organizationUnit'",
                        permissionDependency: new SimplePermissionDependency(PermissionNames.Pages_Systems_OrgUnits)
                   );
            systemRoot.AddItem(organizationunit);


            context.Manager.MainMenu.AddItem(systemRoot);
        }

        /// <summary>
        /// 返回 Vue.js 动态路由
        /// </summary>
        /// <param name="name">路由名称</param>
        /// <param name="path">Url 路径</param>
        /// <param name="hasTitle">菜单显示名称,只是占位符,具体的值从displayName(LocalizableString)获取</param>
        /// <param name="icon">菜单项字体图标名称</param>
        /// <param name="activeMenu">
        /// 当菜的 hidden 属性设置为 true 不显示在菜单栏时,可以指定菜单栏中的某个菜单项为激活状态
        /// 例如:'/Home' 路由的 hidden 属性为 true,当将 activeMenu 属性设置为 '/dashboard' 时,
        /// 当打开 Home 页时,菜单栏中的 Dashboard 项将显示选中状态
        /// </param>
        /// <param name="noCache">如果设置为true,则不会被 <keep-alive> 缓存(默认 false)</param>
        /// <param name="affix">如果设置为true,则显示在顶部横向的 tabel 导航中,当刷新新时,不会从顶部的 tabel 导航中消失(并且不可被删除)</param>
        /// <param name="breadcrumb">如果设置为false,则不会在breadcrumb面包屑中显示</param>
        /// <param name="redirect">当设置 noRedirect 的时候该路由在面包屑导航中不可被点击</param>
        /// <param name="componet">路由所对应的组件</param>
        /// <param name="isHidden">是否显示在菜单栏中</param>
        /// <param name="alwaysShow">
        /// 是否一直显示在菜单栏中
        /// 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面
        /// 只有一个时,会将那个子路由当做根路由显示在侧边栏--如引导页面
        /// 若你想不管路由下面的 children 声明的个数都显示你的根路由
        /// 你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则,一直显示根路由
        /// </param>
        /// <returns></returns>
        private MenuItemDefinition GetMenuItemDefinition(string name, string localizableName, string path, bool isAuth, bool hasMeta,
            string icon = "", string activeMenu = "", bool hasTitle = true,
            bool? noCache = null, bool? affix = null, bool? breadcrumb = null, string redirect = "", string componet = "'Layout'",
            bool isHidden = false, bool? alwaysShow = null, IPermissionDependency permissionDependency = null, object customerData = null)
        {
            return new MenuItemDefinition(
             name,
             new LocalizableString(localizableName, FrameworkConsts.LocalizationSourceName), // 系统设置
             url: path,
             isVisible: isHidden,
             requiresAuthentication: isAuth,
             permissionDependency: permissionDependency,
             customData: GetVueRouter(hasMeta, icon, activeMenu, hasTitle, alwaysShow, noCache, affix, breadcrumb, redirect, componet, customerData)
             );
        }

        /// <summary>
        /// 返回 Vue.js 动态路由
        /// </summary>  
        /// <param name="hasTitle">菜单显示名称,只是占位符,具体的值从displayName(LocalizableString)获取</param>
        /// <param name="icon">菜单项字体图标名称</param>
        /// <param name="activeMenu">
        /// 当菜的 hidden 属性设置为 true 不显示在菜单栏时,可以指定菜单栏中的某个菜单项为激活状态
        /// 例如:'/Home' 路由的 hidden 属性为 true,当将 activeMenu 属性设置为 '/dashboard' 时,
        /// 当打开 Home 页时,菜单栏中的 Dashboard 项将显示选中状态
        /// </param>
        /// <param name="noCache">如果设置为true,则不会被 <keep-alive> 缓存(默认 false)</param>
        /// <param name="affix">如果设置为true,则显示在顶部横向的 tabel 导航中,当刷新新时,不会从顶部的 tabel 导航中消失(并且不可被删除)</param>
        /// <param name="breadcrumb">如果设置为false,则不会在breadcrumb面包屑中显示</param>
        /// <param name="redirect">当设置 noRedirect 的时候该路由在面包屑导航中不可被点击</param>
        /// <param name="componet">路由所对应的组件</param>
        /// <param name="isHidden">是否显示在菜单栏中</param>
        /// <param name="alwaysShow">
        /// 是否一直显示在菜单栏中
        /// 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面
        /// 只有一个时,会将那个子路由当做根路由显示在侧边栏--如引导页面
        /// 若你想不管路由下面的 children 声明的个数都显示你的根路由
        /// 你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则,一直显示根路由
        /// 如果没有 children 属性必须设置为 false 否则会出下下拉图示
        /// </param>
        /// <returns></returns>
        private JObject GetVueRouter(bool hasMeta, string icon = "", string activeMenu = "", bool hasTitle = true, bool? alwaysShow = null,
            bool? noCache = null, bool? affix = null, bool? breadcrumb = null, string redirect = "", string componet = "", Object customerData = null)
        {
            JObject vueRouter = new JObject();
            if (alwaysShow.HasValue)
            {
                vueRouter["alwaysShow"] = alwaysShow.Value;
            }
            if (!string.IsNullOrWhiteSpace(componet))
            {
                vueRouter["component"] = componet;
            }
            if (hasMeta)
            {
                vueRouter["meta"] = new JObject();
                if (hasTitle)
                {
                    // 只作占位符,实际取值是从 MenuItemDefinition.DisplayName 中获取
                    vueRouter["meta"]["title"] = string.Empty;
                }
                if (!string.IsNullOrWhiteSpace(icon))
                {
                    vueRouter["meta"]["icon"] = icon;
                }
                if (noCache.HasValue)
                {
                    vueRouter["meta"]["noCache"] = noCache;
                }
                if (affix.HasValue)
                {
                    vueRouter["meta"]["affix"] = affix;
                }
                if (breadcrumb.HasValue)
                {
                    vueRouter["meta"]["breadcrumb"] = breadcrumb;
                }
                if (!string.IsNullOrWhiteSpace(activeMenu))
                {
                    vueRouter["meta"]["activeMenu"] = activeMenu;
                }
                if (customerData != null)
                {
                    vueRouter.Merge(JToken.FromObject(customerData));
                }
            }
            if (!string.IsNullOrWhiteSpace(redirect))
            {
                vueRouter["redirect"] = redirect;
            }
            return vueRouter;
        }
    }
}

 AbpFramework.Application》Roles
注入:private readonly ILocalizationContext _localContext;
新增接口:注意更改接口IRoleAppService

 /// <summary>
        /// 获取角色对应的权限
        /// </summary>
        /// <returns></returns>
        public Task<ListResultDto<RoleDto>> GetAllRoles()
        {
            var roleList = _roleManager.Roles.ToList();
            return Task.FromResult(
                new ListResultDto<RoleDto>
                {
                    Items = roleList.Select(MapToEntityDto).ToList()
                }
            );
        }

        /// <summary>
        /// 获取角色对应的权限
        /// </summary>
        /// <returns></returns>
        public async Task<ListResultDto<PermissionData>> GetRolePermissionDatas()
        {
            //获取所有权限
            var permissions = PermissionManager.GetAllPermissions().Select(s => new ProcessPermission
            {
                Name = s.Name,
                DisplayName = s.DisplayName,
                IsProcess = false
            }).ToList();
            var allPermissions = new List<PermissionData>();
            //递归获取数据
            for (var i = 0; i < permissions.Count; i++)
            {
                var permission = permissions[i];
                if (!permission.IsProcess)
                {
                    var name = permission.Name;
                    var permissionData = new PermissionData()
                    {
                        Name = name,
                        Label = permission.DisplayName.Localize(_localContext),
                        Children = new List<PermissionData>()
                    };
                    //查询该权限下是否有子权限
                    var pointCount = name.Split('.').Count();
                    var processList = permissions.Where(w => w.Name.Split('.').Count() == pointCount + 1 && w.Name.Contains(name)).ToList();
                    if (processList.Count > 0)
                    {
                        processPermission(permissions, permissionData, processList);
                    }
                    allPermissions.Add(permissionData);
                }

            }
            return new ListResultDto<PermissionData>
            {
                Items = allPermissions
            };
        }

        private void processPermission(List<ProcessPermission> allPermissions, PermissionData permissionData, List<ProcessPermission> permissions)
        {
            for (var j = 0; j < permissions.Count; j++)
            {
                var childPermission = permissions[j];
                var childName = childPermission.Name;
                var childPermissionData = new PermissionData()
                {
                    Name = childName,
                    Label = childPermission.DisplayName.Localize(_localContext),
                    Children = new List<PermissionData>()
                };
                permissionData.Children.Add(childPermissionData);
                childPermission.IsProcess = true;
                //查询该权限下是否有子权限
                var childPointCount = childName.Split('.').Count();
                var childProcessList = permissions.Where(w => w.Name.Split('.').Count() == childPointCount + 1 && w.Name.Contains(childName)).ToList();
                if (childProcessList.Count > 0)
                {
                    processPermission(allPermissions, childPermissionData, childProcessList);
                }
            }
        }
View Code

附加登录:默认是启用多租户的,所以前端调用接口登录的时候要传一个默认的租户名称,要修改登录接口AbpFramework.Web》AccountController》Login:

[HttpPost]
        [DisableAuditing]
        public async Task<JsonResult> Login(LoginViewModel loginModel, string returnUrl = "", string returnUrlHash = "")
        {
            CheckModelState();
            //前端传一个默认的 Default 租户名称,如果没有传再自动获取。
            string tenancyName = string.IsNullOrEmpty(loginModel.TenancyName) ? GetTenancyNameOrNull() : loginModel.TenancyName;
            var loginResult = await GetLoginResultAsync(
                loginModel.UsernameOrEmailAddress,
                loginModel.Password,
                tenancyName
                );

            await SignInAsync(loginResult.User, loginResult.Identity, loginModel.RememberMe);

            if (string.IsNullOrWhiteSpace(returnUrl))
            {
                returnUrl = Request.ApplicationPath;
            }

            if (!string.IsNullOrWhiteSpace(returnUrlHash))
            {
                returnUrl = returnUrl + returnUrlHash;
            }

            return Json(new AjaxResponse { TargetUrl = returnUrl });
        }

参考:https://www.cnblogs.com/defzhu/p/4843292.html

https://www.cnblogs.com/kid1412/p/6006297.html

https://www.cnblogs.com/wendj/p/6812942.html

posted on 2018-11-01 10:46  邢帅杰  阅读(956)  评论(0编辑  收藏  举报