我的编程空间,编程开发者的网络收藏夹
学习永远不晚

ASP.NET Core中的策略授权和ABP授权

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

ASP.NET Core中的策略授权和ABP授权

ASP.NET Core 中的策略授权

首先我们来创建一个 WebAPI 应用。

然后引入 Microsoft.AspNetCore.Authentication.JwtBearer 包。

策略

Startup 类的 ConfigureServices 方法中,添加一个策略的形式如下:

    services.AddAuthorization(options =>
    {
        options.AddPolicy("AtLeast21", policy =>
            policy.Requirements.Add(new MinimumAgeRequirement(21)));
    });

这里我们分步来说。

services.AddAuthorization 用于添加授权方式,目前只支持 AddPolicy。

ASP.NET Core 中,有基于角色、声明、策略的三种授权形式,都是使用 AddPolicy 来添加授权处理。

其中,有两个 API 如下:

        public void AddPolicy(string name, AuthorizationPolicy policy);
        public void AddPolicy(string name, Action<AuthorizationPolicyBuilder> configurePolicy);

name = "AtLeast21",这里 "AtLeast21" 是策略的名称。

policy.Requirements.Add() 用于添加一个策略的标记(存储此策略的数据),此标记需要继承 IAuthorizationRequirement 接口。

策略的名称应该如何设置呢?在授权上应该如何编写策略以及使用 Requirements.Add()

这里先放一放,我们接下来再讲解。

定义一个 Controller

我们来添加一个 Controller :

    [ApiController]
    [Route("[controller]")]
    public class BookController : ControllerBase
    {
        private static List<string> BookContent = new List<string>();
        [HttpGet("Add")]
        public string AddContent(string body)
        {
            BookContent.Add(body);
            return "success";
        }

        [HttpGet("Remove")]
        public string RemoveContent(int n)
        {
            BookContent.Remove(BookContent[n]);
            return "success";
        }

        [HttpGet("Select")]
        public List<object> SelectContent()
        {
            List<object> obj = new List<object>();
            int i = 0;
            foreach (var item in BookContent)
            {
                int tmp = i;
                i++;
                obj.Add(new { Num = tmp, Body = item });
            }
            return obj;
        }

        [HttpGet("Update")]
        public string UpdateContent(int n, string body)
        {
            BookContent[n] = body;
            return "success";
        }
    }

功能很简单,就是对列表内容增删查改。

设定权限

前面我们创建了 BookController ,具有增删查改的功能。应该为每一个功能都应该设置一种权限。

ASP.NET Core 中,一个权限标记,需要继承IAuthorizationRequirement 接口。

我们来设置五个权限:

添加一个文件,填写以下代码。

    

    // 能够访问 Book 的权限
    public class BookRequirment : IAuthorizationRequirement
    {
    }

    // 增删查改 Book 权限
    // 可以继承 IAuthorizationRequirement ,也可以继承 BookRequirment
    public class BookAddRequirment : BookRequirment
    {
    }
    public class BookRemoveRequirment : BookRequirment
    {
    }
    public class BookSelectRequirment : BookRequirment
    {
    }
    public class BookUpdateRequirment : BookRequirment
    {
    }

BookRequirment 代表能够访问 BookController,其它四个分别代表增删查改的权限。

定义策略

权限设定后,我们开始设置策略。

在 Startup 的 ConfigureServices 中,添加:

            services.AddAuthorization(options =>
            {
                options.AddPolicy("Book", policy =>
                {
                    policy.Requirements.Add(new BookRequirment());
                });

                options.AddPolicy("Book:Add", policy =>
                {
                    policy.Requirements.Add(new BookAddRequirment());
                });

                options.AddPolicy("Book:Remove", policy =>
                {
                    policy.Requirements.Add(new BookRemoveRequirment());
                });

                options.AddPolicy("Book:Select", policy =>
                {
                    policy.Requirements.Add(new BookSelectRequirment());
                });

                options.AddPolicy("Book:Update", policy =>
                {
                    policy.Requirements.Add(new BookUpdateRequirment());
                });

            });

这里我们为每种策略只设置一种权限,当然每种策略都可以添加多个权限,

这里名称使用 : 隔开,主要是为了可读性,让人一看就知道是层次关系。

存储用户信息

这里为了更加简单,就不使用数据库了。

以下用户信息结构是随便写的。用户-角色-角色具有的权限。

这个权限用什么类型存储都可以。只要能够标识区分是哪个权限就行。

    /// <summary>
    /// 存储用户信息
    /// </summary>
    public static class UsersData
    {
        public static readonly List<User> Users = new List<User>();
        static UsersData()
        {
            // 添加一个管理员
            Users.Add(new User
            {
                Name = "admin",
                Email = "admin@admin.com",
                Role = new Role
                {
                    Requirements = new List<Type>
                    {
                        typeof( BookRequirment),
                        typeof( BookAddRequirment),
                        typeof( BookRemoveRequirment),
                        typeof( BookSelectRequirment),
                        typeof( BookUpdateRequirment)
                    }
                }
            });

            // 没有删除权限
            Users.Add(new User
            {
                Name = "作者",
                Email = "wirter",
                Role = new Role
                {
                    Requirements = new List<Type>
                    {
                        typeof( BookRequirment),
                        typeof( BookAddRequirment),
                        typeof( BookRemoveRequirment),
                        typeof( BookSelectRequirment),
                    }
                }
            });
        }
    }

    public class User
    {
        public string Name { get; set; }
        public string Email { get; set; }
        public Role Role { get; set; }
    }

    /// <summary>
    /// 这里的存储角色的策略授权,字符串数字等都行,只要能够存储表示就OK
    /// <para>在这里没有任何意义,只是标识的一种方式</param>
    /// </summary>
    public class Role
    {
        public List<Type> Requirements { get; set; }
    }

标记访问权限

定义策略完毕后,就要为 Controller 和 Action 标记访问权限了。

使用 [Authorize(Policy = "{string}")] 特性和属性来设置访问此 Controller 、 Action 所需要的权限。

这里我们分开设置,每个功能标记一种权限(最小粒度应该是一个功能 ,而不是一个 API)。

    [Authorize(Policy = "Book")]
    [ApiController]
    [Route("[controller]")]
    public class BookController : ControllerBase
    {
        private static List<string> BookContent = new List<string>();

        [Authorize(Policy = "Book:Add")]
        [HttpGet("Add")]
        public string AddContent(string body){}

        [Authorize(Policy = "Book:Remove")]
        [HttpGet("Remove")]
        public string RemoveContent(int n){}

        [Authorize(Policy = "Book:Select")]
        [HttpGet("Select")]
        public List<object> SelectContent(){}

        [Authorize(Policy = "Book:Update")]
        [HttpGet("Update")]
        public string UpdateContent(int n, string body){}
    }

认证:Token 凭据

因为使用的是 WebAPI,所以使用 Bearer Token 认证,当然使用 Cookie 等也可以。使用什么认证方式都可以。

            // 设置验证方式为 Bearer Token
            // 添加 using Microsoft.AspNetCore.Authentication.JwtBearer;
            // 你也可以使用 字符串 "Brearer" 代替 JwtBearerDefaults.AuthenticationScheme
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuerSigningKey = true,
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("abcdABCD1234abcdABCD1234")),    // 加密解密Token的密钥

                        // 是否验证发布者
                        ValidateIssuer = true,
                        // 发布者名称
                        ValidIssuer = "server",

                        // 是否验证订阅者
                        // 订阅者名称
                        ValidateAudience = true,
                        ValidAudience = "client007",

                        // 是否验证令牌有效期
                        ValidateLifetime = true,
                        // 每次颁发令牌,令牌有效时间
                        ClockSkew = TimeSpan.FromMinutes(120)
                    };
                });

上面的代码是一个模板,可以随便改。这里的认证方式跟我们的策略授权没什么关系。

颁发登录凭据

下面这个 Action 放置到 BookController,作为登录功能。这一部分也不重要,主要是为用户颁发凭据,以及标识用户。用户的 Claim 可以存储此用户的唯一标识。

        /// <summary>
        /// 用户登录并且颁发凭据
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet("Token")]
        public string Token(string name)
        {
            User user = UsersData.Users.FirstOrDefault(x => x.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
            if (user is null)
                return "未找到此用户";

            // 定义用户信息
            var claims = new Claim[]
            {
                new Claim(ClaimTypes.Name, name),
                new Claim(JwtRegisteredClaimNames.Email, user.Email)
            };

            // 和 Startup 中的配置一致
            SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("abcdABCD1234abcdABCD1234"));

            JwtSecurityToken token = new JwtSecurityToken(
                issuer: "server",
                audience: "client007",
                claims: claims,
                notBefore: DateTime.Now,
                expires: DateTime.Now.AddMinutes(30),
                signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
            );

            string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);
            return jwtToken;
        }

Configure 中补充以下两行:

            app.UseAuthentication();
            app.UseAuthorization();

自定义授权

自定义授权需要继承 IAuthorizationHandler 接口,实现此接口的类能够决定是否对用户的访问进行授权。

实现代码如下:

    /// <summary>
    /// 判断用户是否具有权限
    /// </summary>
    public class PermissionHandler : IAuthorizationHandler
    {
        public async Task HandleAsync(AuthorizationHandlerContext context)
        {
            // 当前访问 Controller/Action 所需要的权限(策略授权)
            IAuthorizationRequirement[] pendingRequirements = context.PendingRequirements.ToArray();

            // 取出用户信息
            IEnumerable<Claim> claims = context.User?.Claims;

            // 未登录或者取不到用户信息
            if (claims is null)
            {
                context.Fail();
                return;
            }


            // 取出用户名
            Claim userName = claims.FirstOrDefault(x => x.Type == ClaimTypes.Name);
            if (userName is null)
            {
                context.Fail();
                return;
            }
            // ... 省略一些检验过程 ...

            // 获取此用户的信息
            User user = UsersData.Users.FirstOrDefault(x => x.Name.Equals(userName.Value, StringComparison.OrdinalIgnoreCase));
            List<Type> auths = user.Role.Requirements;

            // 逐个检查
            foreach (IAuthorizationRequirement requirement in pendingRequirements)
            {
                // 如果用户权限列表中没有找到此权限的话
                if (!auths.Any(x => x == requirement.GetType()))
                    context.Fail();

                context.Succeed(requirement);
            }

            await Task.CompletedTask;
        }
    }

过程:

  • 从上下文(Context) 中获取用户信息(context.User)
  • 获取此用户所属的角色,并获取此角色具有的权限
  • 获取此次请求的 Controller/Action 需要的权限(context.PendingRequirements)
  • 检查所需要的权限(foreach循环),此用户是否都具有

最后需要将此接口、服务,注册到容器中:

services.AddSingleton<IAuthorizationHandler, PermissionHandler>();

做完这些后,就可以测试授权了。

IAuthorizationService

前面实现了 IAuthorizationHandler 接口的类,用于自定义确定用户是否有权访问此 Controller/Action。

IAuthorizationService 接口用于确定授权是否成功,其定义如下:

public interface IAuthorizationService
    {
        Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object? resource, IEnumerable<IAuthorizationRequirement> requirements);

        Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object? resource, string policyName);
    }

DefaultAuthorizationService 接口实现了 IAuthorizationService ,ASP.NET Core 默认使用 DefaultAuthorizationService 来确认授权。

前面我们使用 IAuthorizationHandler 接口来自定义授权,如果再深入一层的话,就追溯到了IAuthorizationService

DefaultAuthorizationService 是 IAuthorizationService 的默认实现,其中有一段代码如下:

DefaultAuthorizationService 比较复杂,一般情况下,我们只要实现 IAuthorizationHandler 就够了。

参考资料:https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.authorization.defaultauthorizationservice?view=aspnetcore-3.1

ABP 授权

前面已经介绍了 ASP.NET Core 中的策略授权,这里介绍一下 ABP 中的授权,我们继续利用前面已经实现的 ASP.NET Core 代码。

创建 ABP 应用

Nuget 安装 Volo.Abp.AspNetCore.MvcVolo.Abp.Autofac 。

创建 AppModule 类,代码如下:

    [DependsOn(typeof(AbpAspNetCoreMvcModule))]
    [DependsOn(typeof(AbpAutofacModule))]
    public class AppModule : AbpModule
    {
        public override void OnApplicationInitialization(
            ApplicationInitializationContext context)
        {
            var app = context.GetApplicationBuilder();
            var env = context.GetEnvironment();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
            }

            app.UseStaticFiles();
            app.UseRouting();
            app.UseConfiguredEndpoints();
        }
    }

在 Program 的 Host 加上 .UseServiceProviderFactory(new AutofacServiceProviderFactory()),示例如下:

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .UseServiceProviderFactory(new AutofacServiceProviderFactory())
            ...
            ...

然后在 Startup 中的 ConfiguraServices 方法中,添加 ABP 模块, 并且设置使用 Autofac。

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddApplication<AppModule>(options=>
            {
                options.UseAutofac();
            });
        }

定义权限

ABP 中使用 PermissionDefinitionProvider 类来定义权限,创建一个类,其代码如下:

    public class BookPermissionDefinitionProvider : PermissionDefinitionProvider
    {
        public override void Define(IPermissionDefinitionContext context)
        {
            var myGroup = context.AddGroup("Book");
            var permission = myGroup.AddPermission("Book");
            permission.AddChild("Book:Add");
            permission.AddChild("Book:Remove");
            permission.AddChild("Book:Select");
            permission.AddChild("Book:Update");
        }
    }

这里定义了一个组 Book,定义了一个权限 Book了,Book 其下有四个子权限。

删除 Startup 中的services.AddAuthorization(options =>... 。

将剩余的依赖注入服务代码移动到 AppModule 的 ConfigureServices 中。

Startup 的 Configure 改成:

            app.InitializeApplication();

AbpModule 中的 Configure 改成:

            var app = context.GetApplicationBuilder();
            var env = context.GetEnvironment();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
            }

            app.UseStaticFiles();
            app.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseConfiguredEndpoints();

PermissionHandler 需要改成:

    public class PermissionHandler : IAuthorizationHandler
    {
        public Task HandleAsync(AuthorizationHandlerContext context)
        {
            // 当前访问 Controller/Action 所需要的权限(策略授权)
            IAuthorizationRequirement[] pendingRequirements = context.PendingRequirements.ToArray();

            // 逐个检查
            foreach (IAuthorizationRequirement requirement in pendingRequirements)
            {
                context.Succeed(requirement);
            }


            return Task.CompletedTask;
        }
    }

删除 UserData 文件;BookController 需要修改一下登录和凭证。

到此这篇关于ASP.NET Core策略授权和ABP授权的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

ASP.NET Core中的策略授权和ABP授权

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

ASP.NET Core中策略授权和ABP授权怎么用

小编给大家分享一下ASP.NET Core中策略授权和ABP授权怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!ASP.NET Core 中的策略授权首先我们
2023-06-29

ASP.NET Core使用JWT认证授权的方法

demo地址: https://github.com/william0705/JWTS 名词解析认证 : 识别用户是否合法 授权: 赋予用户权限 (能访问哪些资源) 鉴权: 鉴定权限是否合法 Jwt优势与劣势优势1、 无状态 token
2022-06-07

ASP.NET Core按用户等级授权的方法

本文章详细介绍了ASP.NETCore中基于用户等级的授权方法,包括定义用户等级和权限、将授权策略应用于控制器和操作等步骤。使用用户等级授权的好处包含了:更细粒度的控制可扩展性更好的安全性通过实施用户等级授权,开发者可以确保只有拥有适当权限的用户才能访问ASP.NETCore应用程序中的特定资源或功能。
ASP.NET Core按用户等级授权的方法
2024-04-02

Asp.Net Core 企业微信静默授权的实现

企业微信接口文档 1. 构造授权网页链接2.回调获取到 Code 通过code+access_token去 请求用户信息3. 获取access_token调试准备工作 -->内网穿透+域名 推荐向日葵有免费的,免费的开发测试够用了 域名的配
2022-06-07

浅谈ASP.NET Core 中jwt授权认证的流程原理

1,快速实现授权验证 什么是 JWT ?为什么要用 JWT ?JWT 的组成? 这些百度可以直接找到,这里不再赘述。 实际上,只需要知道 JWT 认证模式是使用一段 Token 作为认证依据的手段。 我们看一下 Postman 设置 Tok
2022-06-07

ASP.NET Core 6.0怎么添加JWT认证和授权功能

本篇内容介绍了“ASP.NET Core 6.0怎么添加JWT认证和授权功能”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!相关名词Authe
2023-06-30

ASP.NET Core如何使用JWT自定义角色并实现策略授权需要的接口

ASP.NET Core如何使用JWT自定义角色并实现策略授权需要的接口,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。① 存储角色/用户所能访问的 API例如使
2023-06-26

掌握 ASP Core 中的身份验证和授权的艺术

ASP Core 中的身份验证和授权的艺术
掌握 ASP Core 中的身份验证和授权的艺术
2024-03-07

ASP.NET Core 3.0轻量级角色API控制授权库的方法是什么

本文小编为大家详细介绍“ASP.NET Core 3.0轻量级角色API控制授权库的方法是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“ASP.NET Core 3.0轻量级角色API控制授权库的方法是什么”文章能帮助大家解决疑惑,下
2023-06-26

如何处理PHP开发中的用户认证和授权

随着互联网的快速发展,网站和应用程序的用户认证和授权变得越来越重要。对于PHP开发者来说,确保用户的身份验证和权限管理是至关重要的。本文将介绍PHP开发中的用户认证和授权的基本概念,并提供具体的代码示例,以帮助读者更好地理解和实践。用户认证
2023-10-21

如何解决PHP开发中的身份认证和授权

身份认证和授权是Web开发中非常重要的一部分,特别是在涉及到用户登录、访问权限管理等场景下。本文将介绍如何解决PHP开发中的身份认证和授权,并提供具体的代码示例。一、身份认证身份认证是指验证用户的身份是否合法,常用的身份认证方式有基于表单的
2023-10-21

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录