原文: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说明

 
image

这个图是基本的结构和运行图,我们可以创建多个中间组件,组成一个管道,在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
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

ASP.Net Core下Authorization的几种方式 - 简书的更多相关文章

  1. Asp.Net Core下的两种路由配置方式

    与Asp.Net Mvc创建区域的时候会自动为你创建区域路由方式不同的是,Asp.Net Core下需要自己手动做一些配置,但更灵活了. 我们先创建一个区域,如下图 然后我们启动访问/Manage/H ...

  2. 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获

    项目开发中的一些注意事项以及技巧总结   1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...

  3. Asp.net core下利用EF core实现从数据实现多租户(3): 按Schema分离 附加:EF Migration 操作

    前言 前段时间写了EF core实现多租户的文章,实现了根据数据库,数据表进行多租户数据隔离. 今天开始写按照Schema分离的文章. 其实还有一种,是通过在数据表内添加一个字段做多租户的,但是这种模 ...

  4. ASP.NET CORE下运行CMD命令

    ASP.NET CORE下运行CMD命令,用以前的ASP.NET 的命令System.Diagnostics.Process.Start("notepad");这样是可以运行出记事 ...

  5. Asp.net core下利用EF core实现从数据实现多租户(1)

    前言 随着互联网的的高速发展,大多数的公司由于一开始使用的传统的硬件/软件架构,导致在业务不断发展的同时,系统也逐渐地逼近传统结构的极限. 于是,系统也急需进行结构上的升级换代. 在服务端,系统的I/ ...

  6. ASP.NET Core下FreeSql的仓储事务

    ASP.NET Core下FreeSql的仓储事务 第一步:配置 Startup.cs 注入 引入包 dotnet add package FreeSql dotnet add package Fre ...

  7. ASP.NET 页面之间传值的几种方式

    开篇概述 对于任何一个初学者来说,页面之间传值可谓是必经之路,却又是他们的难点.其实,对大部分高手来说,未必不是难点. 回想2016年面试的将近300人中,有实习生,有应届毕业生,有1-3年经验的,有 ...

  8. 【ASP.NET MVC系列】浅谈ASP.NET 页面之间传值的几种方式

    ASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作 ...

  9. ASP.NET页面间传值的几种方式

    ASP.NET页面间传值的几种方式 1.使用QueryString 使用QuerySting在页面间传递值已经是一种很老的机制了,这种方法的主要优点是实现起来非常简单,然而它的缺点是传递的值是会显示在 ...

随机推荐

  1. 关于OpenModelica的编译

    由于工作需要,最近对OpenModelica进行二次开发,由于国内资料也比较少,所以踩了一些坑,近期计划把OpenModelica的编译,msys,及OpenModelica里面比较关键的部分OMEd ...

  2. Python: sklearn库——数据预处理

    Python: sklearn库 —— 数据预处理 数据集转换之预处理数据:      将输入的数据转化成机器学习算法可以使用的数据.包含特征提取和标准化.      原因:数据集的标准化(服从均值为 ...

  3. 标准C++常用头文件及描述

    #include <algorithm> //STL 通用算法 #include <bitset> //STL 位集容器 #include <cctype> //字 ...

  4. webpack对vue单文件组件的解析

    vue2.0 Step0: 首先vuelLoaderPlugin会在webpack初始化的时候 注入pitcher这个rule,然后将rules进行排序, [pitcher,...clonedRule ...

  5. pyqt5 工具栏文字图片同时显示

    import sys from PyQt5.QtWidgets import QMainWindow, QTextEdit, QAction, QApplication from PyQt5.QtGu ...

  6. Web jsp开发学习——数据库的另一种连接方式(配置静态数据库连接池)

    1.导包   2.找到sever里的sever.xml,配置静态数据库连接池 <Context docBase="bookstore" path="/booksto ...

  7. CnPack开发包基础库

    unit CnCommon; {* |<PRE> ===================================================================== ...

  8. 【D3D12学习手记】The Command Queue and Command Lists

    GPU有一个命令队列,CPU通过Direct3D API将命令提交到队列里来使用命令列表(command lists),如下图.当一套命令(a set of commands)已经被提交到命令队列,他 ...

  9. Unity中的动画系统和Timeline(3) 模型和动画导入

    动画导入 美工做好的模型,直接将文件夹拖进来就导入好了.导入模型后,检查模型的材质贴图等是否丢失,若丢失,根据名字补上.如果美工取名规范,一一对应的话,就很简单.如果不是,那就呵呵哒. 有的美工做的比 ...

  10. re 正则匹配的非贪婪匹配

    非贪婪匹配 将尽可能少的匹配内容,当?出现在其他的重复次数后面时会将贪婪模式改为非贪婪模式. ? 如 abc.*? abc.+? 非贪婪匹配:尽可能少的匹配{n,}?{,n}?{n,m}?*? # * ...