Asp.Net Core--自定义基于策略的授权
翻译如下:
在封面下,角色授权和声明授权使用需求,需求的处理程序和预配置的策略。 这些构建块允许您在代码中表示授权评估,从而允许更丰富,可重用和容易测试的授权结构。
授权策略由一个或多个需求组成,并在应用程序启动时作为授权服务配置的一部分注册,在Startup.cs文件中的ConfigureServices中。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(); services.AddAuthorization(options =>
{
options.AddPolicy("Over21",
policy => policy.Requirements.Add(new MinimumAgeRequirement(21)));
}
});
在这里您可以看到一个“Over21”策略创建有一个要求,最小年龄,作为参数传递到需求。
通过指定策略名称,使用Authorize属性应用策略,例如:
[Authorize(Policy="Over21")]
public class AlcoholPurchaseRequirementsController : Controller
{
public ActionResult Login()
{
} public ActionResult Logout()
{
}
}
Requirements(条件/要求)
授权requirement是策略可用于评估当前用户主体的数据参数的集合。 在我们的最低年龄政策中,要求我们有一个单一参数,即最低年龄。 要求必须实现IAuthorizationRequirement。 这是一个空的,标记接口。 参数化的最低年龄要求可以如下实现:
public class MinimumAgeRequirement : IAuthorizationRequirement
{
public MinimumAgeRequirement(int age)
{
MinimumAge = age;
} protected int MinimumAge { get; set; }
}
一个requirement不需要具有数据或属性。
授权处理程序
授权处理程序负责评估requirement的任何属性。 授权处理程序必须根据提供的AuthorizationContext来评估它们,以决定是否允许授权。 一个requirement可以有多个处理器。 处理程序必须继承AuthorizationHandler <T>,其中T是它处理的requirement。
最小年龄处理程序可能如下所示:
public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationContext context, MinimumAgeRequirement requirement)
{
if (!context.User.HasClaim(c => c.Type == ClaimTypes.DateOfBirth &&
c.Issuer == "http://contoso.com"))
{
// .NET 4.x -> return Task.FromResult(0);
return Task.CompletedTask;
} var dateOfBirth = Convert.ToDateTime(context.User.FindFirst(
c => c.Type == ClaimTypes.DateOfBirth && c.Issuer == "http://contoso.com").Value); int calculatedAge = DateTime.Today.Year - dateOfBirth.Year;
if (dateOfBirth > DateTime.Today.AddYears(-calculatedAge))
{
calculatedAge--;
} if (calculatedAge >= requirement.MinimumAge)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
在上面的代码中,我们首先查看当前用户主体是否具有由我们知道和信任的发行方发布的出生日期索赔日期。 如果索赔失踪,我们不能授权,所以我们返回。 如果我们有一个索赔,我们计算出用户的年龄,如果他们满足最低年龄通过的要求,那么授权已经成功。 一旦授权成功,我们调用context.Succeed()在作为参数成功的需求中传递。
处理程序必须在配置期间在服务集合中注册,例如:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(); services.AddAuthorization(options =>
{
options.AddPolicy("Over21",
policy => policy.Requirements.Add(new MinimumAgeRequirement(21)));
}); services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();
}
每个处理程序通过使用services.AddSingleton <AuthorizationHandler,YourHandlerClass>();添加到服务集合。 传入你的处理程序类。
处理程序需要返回什么?
你可以在我们的处理程序示例中看到Handle()方法没有返回值,那么我们如何指示成功或失败?
处理程序通过调用context.Succeed(授权需求要求)来指示成功,传递已成功验证的需求。
处理程序不需要一般处理故障,因为相同需求的其他处理程序可能会成功。
为了保证失败,即使其他处理程序为一个需求成功,调用context.Fail。
无论你在处理程序中调用什么,当策略需要该需求时,将调用一个需求的所有处理程序。 这允许需求具有副作用,例如日志记录,即使在另一个处理程序中调用了context.Fail(),它也总是会发生。
为什么需要多个处理程序?
如果您希望评估基于OR基础,则为单个需求实现多个处理程序。 例如,微软的门只能用钥匙卡打开。 如果你把钥匙卡留在家里,接待员打印一张临时贴纸,为你打开门。 在这种情况下,您将有一个单独的要求,EnterBuilding,但多个处理程序,每个检查单个要求。
public class EnterBuildingRequirement : IAuthorizationRequirement
{
} public class BadgeEntryHandler : AuthorizationHandler<EnterBuildingRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, EnterBuildingRequirement requirement)
{
if (context.User.HasClaim(c => c.Type == ClaimTypes.BadgeId &&
c.Issuer == "http://microsoftsecurity"))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
} public class HasTemporaryStickerHandler : AuthorizationHandler<EnterBuildingRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, EnterBuildingRequirement requirement)
{
if (context.User.HasClaim(c => c.Type == ClaimTypes.TemporaryBadgeId &&
c.Issuer == "https://microsoftsecurity"))
{
// We'd also check the expiration date on the sticker.
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
现在,假设当策略评估输入构建要求时注册两个处理程序,如果任一处理程序成功,则策略评估将成功。
使用Func来实现策略
这里可以是其中完成策略在代码中简单表示的情况。 在使用RequireAssertion策略构建器配置策略时,可以简单地提供Func <AuthorizationHandlerContext,bool>。
例如,以前的BadgeEntryHandler可以被重写如下:
services.AddAuthorization(options =>
{
options.AddPolicy("BadgeEntry",
policy => policy.RequireAssertion(context =>
context.User.HasClaim(c =>
(c.Type == ClaimTypes.BadgeId ||
c.Type == ClaimTypes.TemporaryBadgeId)
&& c.Issuer == "https://microsoftsecurity"));
}));
}
}
在处理程序中访问MVC请求上下文
您必须在授权处理程序中实现的Handle方法有两个参数:AuthorizationContext和要处理的要求。 框架(如MVC或Jabbr)可以向AuthorizationContext的Resource属性添加任何对象,以传递额外信息。
例如,MVC在resource属性中传递一个Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext的实例,该属性用于访问HttpContext,RouteData和MVC提供的所有内容。
Resource属性的使用是特定于框架的。 使用资源属性中的信息将限制您的授权策略到特定框架。 您应该使用as关键字转换Resource属性,然后检查转换是否成功,以确保您的代码在其他框架上运行时不会与InvalidCastExceptions崩溃;
var mvcContext = context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext; if (mvcContext != null)
{
// Examine MVC specific things like routing data.
}
Asp.Net Core--自定义基于策略的授权的更多相关文章
- asp.net core 自定义基于 HttpContext 的 Serilog Enricher
asp.net core 自定义基于 HttpContext 的 Serilog Enricher Intro 通过 HttpContext 我们可以拿到很多有用的信息,比如 Path/QuerySt ...
- ASP.NET Core WebApi基于JWT实现接口授权验证
一.ASP.Net Core WebApi JWT课程前言 我们知道,http协议本身是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证,那么下一次请求时,用户还要再 ...
- 【ASP.NET Core】运行原理(4):授权
本系列将分析ASP.NET Core运行原理 [ASP.NET Core]运行原理(1):创建WebHost [ASP.NET Core]运行原理(2):启动WebHost [ASP.NET Core ...
- asp.net core 自定义认证方式--请求头认证
asp.net core 自定义认证方式--请求头认证 Intro 最近开始真正的实践了一些网关的东西,最近写几篇文章分享一下我的实践以及遇到的问题. 本文主要介绍网关后面的服务如何进行认证. 解决思 ...
- asp.net core 自定义 Policy 替换 AllowAnonymous 的行为
asp.net core 自定义 Policy 替换 AllowAnonymous 的行为 Intro 最近对我们的服务进行了改造,原本内部服务在内部可以匿名调用,现在增加了限制,通过 identit ...
- ASP.NET Core WebApi基于Redis实现Token接口安全认证
一.课程介绍 明人不说暗话,跟着阿笨一起玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将会是需要思考的问题.在ASP.NET WebSer ...
- 使用JWT的ASP.NET CORE令牌身份验证和授权(无Cookie)——第1部分
原文:使用JWT的ASP.NET CORE令牌身份验证和授权(无Cookie)--第1部分 原文链接:https://www.codeproject.com/Articles/5160941/ASP- ...
- asp.net core自定义端口
asp.net Core 自定义端口 官方文档 aspnet内库源码: https://github.com/aspnet dotnet系统内库源码:https://github.com/dotnet ...
- 如何在ASP.NET Core自定义中间件中读取Request.Body和Response.Body的内容?
原文:如何在ASP.NET Core自定义中间件中读取Request.Body和Response.Body的内容? 文章名称: 如何在ASP.NET Core自定义中间件读取Request.Body和 ...
随机推荐
- 第39课 Qt中的事件处理(下)
1. 事件的传递过程 (1)操作系统检测到用户动作时,会产生一条系统消息,该消息被发送到Qt应用程序 (2)Qt应用程序收到系统消息后,将其转化为一个对应的QEvent事件对象,并调用QObject: ...
- java之多线程 一
概述: 几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是一个线程. 进程与线程: 进程是指处于运 ...
- [No000080]右键解锁增强Chrome插件开发,破除防复制
昨天用360极速(虽然我不喜欢360.)浏览器,登陆知乎查阅一些东西,突然感觉有些观点很赞同,想copy转载一下,我了个去,它丫的居然不让我复制. 地址:https://www.zhihu.com/q ...
- Struts2 Validation学习
Every input is evil! ------------------------------华丽的分割线----------------------------------- 客户端提交的数 ...
- spring独立事务分析
最近在ssm框架的项目中需要用到独立事务的实现,找了半天,搜集了以下理论知识为实现做准备.事务管理器为datasource (1)Spring在transactiondefinition接口中规定了7 ...
- 微信扫描打开APP下载链接提示代码优化
上一次我发了一篇文章叫“微信打开网址添加在浏览器中打开提示”,里面我发出来了三个代码,分别是纯JS.js+html.jQuery+HTML代码.今天来一个简化版带可以关闭的按钮操作.使用的是纯JS+H ...
- 一个小时快速搭建微信小程序教程
「小程序」这个划时代的产品发布快一周了,互联网技术人都在摩拳擦掌,跃跃欲试.可是小程序目前还在内测,首批只发放了 200 个内测资格(泪流满面).本以为没有 AppID 这个月就与小程序无缘了,庆幸的 ...
- 分享 Ionic 开发 Hybrid App 中遇到的问题以及后期发布 iOS/Android 的方方面面
此篇文章主要整理了最近在使用 Ionic 开发 Hybrid App 过程中遇到的一些疑难点以及后期发布生成 iOS 和 Android 版本过程中的种种问题. 文章目录 Ionic 简介和项目需求介 ...
- 一个 -100.01 的double 在内存中怎么存储的. 一个中文String 在内存中占多少直接 utf-8 / GBK
一.-100.01 的double 在内存中怎么存储的 double双精度数据类型存储格式IEEE 双精度格式为8字节64位,由三个字段组成:52 位小数 f : 11 位偏置指数 e :以及 1 位 ...
- 多兼容的JS获取鼠标坐标
//第一.相对于屏幕 function getMousePos(event) { var e = event || window.event; return {'x':e.screenX,'y':sc ...