ASP.Net Core下Authorization的几种方式 - 简书
原文:ASP.Net Core下Authorization的几种方式 - 简书
ASP.Net Core下Authorization的几种方式
Authorization其目标就是验证Http请求能否通过验证。ASP.Net Core提供了很多种Authorization方式,详细可以参考 微软官方文档。在这里只详细介绍三种方式:
- Policy
- Middleware
- Custom Attribute
1. Policy : 策略授权
先定义一个IAuthorizationRequirement类来定义策略的要求,以下例子支持传递一个age参数。
public class AdultPolicyRequirement : IAuthorizationRequirement
{
public int Age { get; }
public AdultPolicyRequirement(int age)
{
//年龄限制
this.Age = age;
}
}
然后定义策略要求的Handler,当提供的Controller被请求时先根据请求的Http报文来决定是否可以通过验证。
public class AdultAuthorizationHandler : AuthorizationHandler
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AdultPolicyRequirement requirement)
{
//获取当前http请求的context对象
var mvcContext = context.Resource as AuthorizationFilterContext;
//以下代码都不是必须的,只是展示一些使用方法,你可以选择使用
......
//
var age = mvcContext.HttpContext.Request.Query.FirstOrDefault(u => u.Key == "age");
if (age.Value.Count <= 0|| Convert.ToInt16(age.Value[0]) < requirement.Age)
{
context.Fail();
}
else
{
//通过验证,这句代码必须要有
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
还需要在启动时,在services里注册定义的策略和对应的Handler
//添加二种认证策略,一种以12岁为界限,一种是18岁
services.AddAuthorization(options =>
{
options.AddPolicy("Adult1", policy =>
policy.Requirements.Add(new AdultPolicyRequirement(12)));
options.AddPolicy("Adult2", policy =>
policy.Requirements.Add(new AdultPolicyRequirement(18)));
});
//添加策略验证handler
services.AddSingleton();
最后在相应的Controller前加上Authroize特性 [Authorize("Adult1")]
。总体上Policy这种方式比较简单,但是也有不灵活的地方,不同的策略要求都需要提前在services里注册。完整的例子可以参考 PolicySample
2. Middleware: 中间件方式
这种方式并不是专门用于授权,它的用途更广更灵活,它用于在所有Http Request和Response前授权检查、数据处理、错误跳转、日志处理等。详细说明可以参考 官方Middleware说明。
这个图是基本的结构和运行图,我们可以创建多个中间组件,组成一个管道,在Http的Request发出和Response创建之前对HttpContext.Request和HttpContext.Response进行处理。看以下例子,定义了2个中间组件类:
public class AuthorizeMiddleware
{
private readonly RequestDelegate next;
public AuthorizeMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context /* other scoped dependencies */)
{
//以下代码都不是必须的,只是展示一些使用方法,你可以选择使用
...
//这个例子只是修改一下response的header
context.Response.OnStarting(state => {
var httpContext = (HttpContext)state;
httpContext.Response.Headers.Add("test2", "testvalue2");
return Task.FromResult(0);
}, context);
//处理结束转其它中间组件去处理
await next(context);
}
}
public class OtherMiddleware
{
private readonly RequestDelegate next;
public OtherMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context )
{
//这个例子只是修改一下response的header
context.Response.OnStarting(state => {
var httpContext = (HttpContext)state;
httpContext.Response.Headers.Add("test1", "testvalue1" );
return Task.FromResult(0);
}, context);
await next(context);
}
}
这里定义的类不需要实现接口或集成系统的类。只需要给app增加middleware代理类的定义。注意在HttpResponse发出之后就不要再调用next.invoke()。以下三句代码的执行顺序不能弄错。
app.UseMiddleware(typeof(AuthorizeMiddleware));
app.UseMiddleware(typeof(OtherMiddleware));
app.UseMvc();
执行web请求后执行的顺序是:
- 执行AuthorizeMiddleware的invoke方法
- 执行OtherMiddleware的invoke方法
- 执行ValueController的Get方法
- 执行OtherMiddleware的修改header方法
- 执行AuthorizeMiddleware的修改header方法
- 发出Http Response
大家可以自己执行一下代码来理解。代码参考 Github地址
3. Custom Attribute:自定义特性
这里其实是第一种Policy策略和自定义特性的结合,从而实现在Controller的具体方法位置自定义不同参数的Policy策略。
首先需要定义这个Attribute和策略要求类
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class PermissionCheckAttribute : AuthorizeAttribute
{
public string Id { get; set; }
public int Operation { get; set; }
public PermissionCheckAttribute() : base("PermissionCheck")
{
}
}
public class PermissionCheckPolicyRequirement : IAuthorizationRequirement
{
//Add any custom requirement properties if you have them
public PermissionCheckPolicyRequirement()
{
}
}
再定义策略和Attribute对应的Handler处理类
public class PermissionCheckPolicyHandler : AttributeAuthorizationHandler<PermissionCheckPolicyRequirement, PermissionCheckAttribute>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext authoriazationContext,
PermissionCheckPolicyRequirement requirement, IEnumerable<PermissionCheckAttribute> attributes)
{
var context = authoriazationContext.Resource as AuthorizationFilterContext;
foreach (var permissionAttribute in attributes)
{
this.checkPermission(context, permissionAttribute.Id, permissionAttribute.Operation);
}
authoriazationContext.Succeed(requirement);
return Task.FromResult<object>(null);
}
private void checkPermission(AuthorizationFilterContext context, string _Id, int _Operation)
{
if (_Operation > 0)
{
if (_Id != "user1")
{
throw new Exception("不具备操作权限");
}
}
else
{
//dosomething
}
return;
}
}
同样还需要在service里添加策略和策略处理类,这里不贴代码了。最后在Controller里使用带参数的Attribute,类似如下:
[HttpGet]
[PermissionCheck (Id ="user1", Operation=2)]
public IEnumerable Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
[PermissionCheck(Id = "user2", Operation = 4)]
public string Get(int id)
{
return "value";
}
完整的代码参考Github地址
作者:voxer
链接:https://www.jianshu.com/p/0ed4d820809c
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
原文地址:https://www.cnblogs.com/lonelyxmas/p/11888372.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- kubernetes(三)之Docker网络详解
- kubernetes(二)之Docker容器及镜像
- 反向传播算法:定义,概念,可视化
- Go语言(二十一) 常见的模块使用
- kubernetes(一)之Docker基础入门
- Go语言(二十)日志采集项目(二)Etcd的使用
- prometheus入门(一)
- Go语言(十九)日志采集项目之logagent开发(一)
- Go语言(十 八)context&日志项目
- 使用梯度上升欺骗神经网络,让网络进行错误的分类
- Go语言(十七) 配置文件库项目
- Python 相对路径问题:“No such file or directory“
- 基于etcd服务发现的overlay跨多宿主机容器网络
- Go语言(十六) 日志项目升级
- PyQt5 技术篇-设置窗口相对桌面位置,按屏幕比例