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和 ...
随机推荐
- SSH----小小项目的小小总结
嘛,之前学了一下SSH框架,跟人合作写了个小东西参加比赛,(当然我是队长),真的感慨良多~,现在用这篇博客记录下来吧 1.责任心/责任感 首先要说的一点,要有责任心,当你与别人组成一个团队的时候,虽然 ...
- UINavigationController的创建和相关设置---学习笔记四
导航控制器 一.设置字体大小,背景等. 二.自定义返回按钮. 三.设置手势. 一.导航中也有个appearance属性,通过它可以设置所有导航的颜色. 二.自定义返回按钮. 1.首先需要知道的是,要把 ...
- webpack中alias别名配置
resolve:{ alias:{ bootcss:__dirname + '/node_modules/.3.3.7@bootstrap/dist/css/bootstrap.min.css' } ...
- iOS关于NSUserDefaults存,写, 删的问题
我们知道NSUserDefaults可以保存某些信息在本地,例如登录的账号,密码等等,当我们使用NSUserDefaults时,它是将信息写入到本地的一个plist文件里,我们都知道 删除plis ...
- typescript实现react中的批次式更新
欢迎吐槽讨论 前言 笔者在React经常使用setState,在学习过程中作笔记以作总结,欢迎讨论. 关于setState的核心观点 1 . 执行setState不都是异步的. 2 . setStat ...
- IIS部署站点相关经验总结
IIS部署站点相关经验总结 1.IIS和.net4.0安装是有先后顺序的,应该先安装.net framework 4.0,再安装IIS.如果按相反顺序安装的话,IIS中看不到4.0相关的东西,那么只能 ...
- js通过日期计算属于星期几
var arys1 = new Array(); arys1 = "2016-09-25".split('-'); //日期为输入日期,格式为 2013-3-10 var ssda ...
- javascript语法速查表
- cout格式化输出
问题描述: 有N条绳子, 它们的长度分别为Li. 如果从它们中切割出K条相同的绳子的话,这K条绳子每条最长能有多少? (备注:答案保留两位小数) <1>精确到小数点后两位输出 #inclu ...
- Spring MVC 处理静态资源不能访问问题
在web.xml文件中加入如下代码: <servlet-mapping> <servlet-name>default</servlet-name> <url- ...