ASP.Net Core下Authorization的几种方式_nic7968的博客-CSDN博客_.net authorization

baacloud免费翻墙vpn注册使用

来源: ASP.Net Core下Authorization的几种方式_nic7968的博客-CSDN博客_.net authorization

Authorization其目标就是验证Http请求能否通过验证。ASP.NET Core提供了很多种Authorization方式,详细可以参考 微软官方文档。在这里只详细介绍三种方式:

  • Policy
  • Middleware
  • Custom Attribute

1. Policy : 策略授权

先定义一个IAuthorizationRequirement类来定义策略的要求,以下例子支持传递一个age参数。

  1. public class AdultPolicyRequirement : IAuthorizationRequirement
  2. {
  3. public int Age { get; }
  4. public AdultPolicyRequirement(int age)
  5. {
  6. //年龄限制
  7. this.Age = age;
  8. }
  9. }

然后定义策略要求的Handler,当提供的Controller被请求时先根据请求的Http报文来决定是否可以通过验证。

  1. public class AdultAuthorizationHandler : AuthorizationHandler
  2. {
  3. protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AdultPolicyRequirement requirement)
  4. {
  5. //获取当前http请求的context对象
  6. var mvcContext = context.Resource as AuthorizationFilterContext;
  7. //以下代码都不是必须的,只是展示一些使用方法,你可以选择使用
  8. ……
  9. //
  10. var age = mvcContext.HttpContext.Request.Query.FirstOrDefault(u => u.Key == “age”);
  11. if (age.Value.Count <= 0|| Convert.ToInt16(age.Value[0]) < requirement.Age)
  12. {
  13. context.Fail();
  14. }
  15. else
  16. {
  17. //通过验证,这句代码必须要有
  18. context.Succeed(requirement);
  19. }
  20. return Task.CompletedTask;
  21. }
  22. }

还需要在启动时,在services里注册定义的策略和对应的Handler

  1. //添加二种认证策略,一种以12岁为界限,一种是18岁
  2. services.AddAuthorization(options =>
  3. {
  4. options.AddPolicy(“Adult1”, policy =>
  5. policy.Requirements.Add(new AdultPolicyRequirement(12)));
  6. options.AddPolicy(“Adult2”, policy =>
  7. policy.Requirements.Add(new AdultPolicyRequirement(18)));
  8. });
  9. //添加策略验证handler
  10. services.AddSingleton();

最后在相应的Controller前加上Authroize特性 [Authorize("Adult1")]。总体上Policy这种方式比较简单,但是也有不灵活的地方,不同的策略要求都需要提前在services里注册。完整的例子可以参考 PolicySample

2. Middleware: 中间件方式

这种方式并不是专门用于授权,它的用途更广更灵活,它用于在所有Http Request和Response前授权检查、数据处理、错误跳转、日志处理等。详细说明可以参考 官方Middleware说明

image

这个图是基本的结构和运行图,我们可以创建多个中间组件,组成一个管道,在Http的Request发出和Response创建之前对HttpContext.Request和HttpContext.Response进行处理。看以下例子,定义了2个中间组件类:

  1. public class AuthorizeMiddleware
  2. {
  3. private readonly RequestDelegate next;
  4. public AuthorizeMiddleware(RequestDelegate next)
  5. {
  6. this.next = next;
  7. }
  8. public async Task Invoke(HttpContext context /* other scoped dependencies */)
  9. {
  10. //以下代码都不是必须的,只是展示一些使用方法,你可以选择使用
  11. //这个例子只是修改一下response的header
  12. context.Response.OnStarting(state => {
  13. var httpContext = (HttpContext)state;
  14. httpContext.Response.Headers.Add(“test2”, “testvalue2”);
  15. return Task.FromResult(0);
  16. }, context);
  17. //处理结束转其它中间组件去处理
  18. await next(context);
  19. }
  20. }
  1. public class OtherMiddleware
  2. {
  3. private readonly RequestDelegate next;
  4. public OtherMiddleware(RequestDelegate next)
  5. {
  6. this.next = next;
  7. }
  8. public async Task Invoke(HttpContext context )
  9. {
  10. //这个例子只是修改一下response的header
  11. context.Response.OnStarting(state => {
  12. var httpContext = (HttpContext)state;
  13. httpContext.Response.Headers.Add(“test1”, “testvalue1” );
  14. return Task.FromResult(0);
  15. }, context);
  16. await next(context);
  17. }
  18. }

这里定义的类不需要实现接口或集成系统的类。只需要给app增加middleware代理类的定义。注意在HttpResponse发出之后就不要再调用next.invoke()。以下三句代码的执行顺序不能弄错。

  1. app.UseMiddleware(typeof(AuthorizeMiddleware));
  2. app.UseMiddleware(typeof(OtherMiddleware));
  3. app.UseMvc();

执行web请求后执行的顺序是:

  • 执行AuthorizeMiddleware的invoke方法
  • 执行OtherMiddleware的invoke方法
  • 执行ValueController的Get方法
  • 执行OtherMiddleware的修改header方法
  • 执行AuthorizeMiddleware的修改header方法
  • 发出Http Response

大家可以自己执行一下代码来理解。代码参考 Github地址

3. Custom Attribute:自定义特性

这里其实是第一种Policy策略和自定义特性的结合,从而实现在Controller的具体方法位置自定义不同参数的Policy策略。

首先需要定义这个Attribute和策略要求类

  1. [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
  2. public class PermissionCheckAttribute : AuthorizeAttribute
  3. {
  4. public string Id { get; set; }
  5. public int Operation { get; set; }
  6. public PermissionCheckAttribute() : base(“PermissionCheck”)
  7. {
  8. }
  9. }
  10. public class PermissionCheckPolicyRequirement : IAuthorizationRequirement
  11. {
  12. //Add any custom requirement properties if you have them
  13. public PermissionCheckPolicyRequirement()
  14. {
  15. }
  16. }

再定义策略和Attribute对应的Handler处理类

  1. public class PermissionCheckPolicyHandler : AttributeAuthorizationHandler<PermissionCheckPolicyRequirement, PermissionCheckAttribute>
  2. {
  3. protected override Task HandleRequirementAsync(AuthorizationHandlerContext authoriazationContext,
  4. PermissionCheckPolicyRequirement requirement, IEnumerable<PermissionCheckAttribute> attributes)
  5. {
  6. var context = authoriazationContext.Resource as AuthorizationFilterContext;
  7. foreach (var permissionAttribute in attributes)
  8. {
  9. this.checkPermission(context, permissionAttribute.Id, permissionAttribute.Operation);
  10. }
  11. authoriazationContext.Succeed(requirement);
  12. return Task.FromResult<object>(null);
  13. }
  14. private void checkPermission(AuthorizationFilterContext context, string _Id, int _Operation)
  15. {
  16. if (_Operation > 0)
  17. {
  18. if (_Id != “user1”)
  19. {
  20. throw new Exception(“不具备操作权限”);
  21. }
  22. }
  23. else
  24. {
  25. //dosomething
  26. }
  27. return;
  28. }
  29. }

同样还需要在service里添加策略和策略处理类,这里不贴代码了。最后在Controller里使用带参数的Attribute,类似如下:

  1. [HttpGet]
  2. [PermissionCheck (Id =“user1”, Operation=2)]
  3. public IEnumerable Get()
  4. {
  5. return new string[] { “value1”, “value2” };
  6. }
  7. // GET api/values/5
  8. [HttpGet(“{id}”)]
  9. [PermissionCheck(Id = “user2”, Operation = 4)]
  10. public string Get(int id)
  11. {
  12. return “value”;
  13. }

完整的代码参考Github地址

作者:voxer
链接:https://www.jianshu.com/p/0ed4d820809c

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏