Security » Authorization » 基于自定义策略的授权
Custom Policy-Based Authorization¶ 基于自定义策略的授权
Underneath the covers the role authorization and claims authorization make use of a requirement, a handler for the requirement and a pre-configured policy. These building blocks allow you to express authorization evaluations in code, allowing for a richer, reusable, and easily testable authorization structure.
下面的内容覆盖了role authorization(角色授权) 和claims authorization(声明授权),确保了要求、要求的句柄以及一个预配制策略的使用,这些搭建好的模块允许你在代码中表达授权检测,允许多重的、可重用的以及易于测试的授权结构。
An authorization policy is made up of one or more requirements and registered at application startup as part of the Authorization service configuration, in ConfigureServices
in the Startup.cs file.
一个授权策略由一个或者多个要求组成,并且作为授权服务配置的一部分在应用启动阶段进行注册(在Startup.cs文件的ConfigureServices 中)。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(); services.AddAuthorization(options =>
{
options.AddPolicy("Over21",
policy => policy.Requirements.Add(new MinimumAgeRequirement()));
}
});
Here you can see an “Over21” policy is created with a single requirement, that of a minimum age, which is passed as a parameter to the requirement.
此处,你可看到新建的“Over21”策略使用了单项需求,表明了最小的年龄要求,并作为一个参数传递给需求。
Policies are applied using the Authorize
attribute by specifying the policy name, for example;
通过指定策略名称,使用Authorize 属性应用了该策略:
[Authorize(Policy="Over21")]
public class AlcoholPurchaseRequirementsController : Controller
{
public ActionResult Login()
{
} public ActionResult Logout()
{
}
}
Requirements¶ 要求
An authorization requirement is a collection of data parameters that a policy can use to evaluate the current user principal. In our Minimum Age policy the requirement we have a single parameter, the minimum age. A requirement must implement IAuthorizationRequirement
. This is an empty, marker interface. A parameterized minimum age requirement might be implemented as follows;
授权要求是一个数据参数组成的集合,这些参数可由策略使用来检测当前用户是否是授权用户。在最小年龄策略要求中,有一个单个参数,表示最小年龄。一个要求必须继承IAuthorizationRequirement。这是一个空的、起到标记作用的接口。参数化的最小年龄要求可以像下面这样进行继承。
public class MinimumAgeRequirement : IAuthorizationRequirement
{
public MinimumAgeRequirement(int age)
{
MinimumAge = age;
} protected int MinimumAge { get; set; }
}
A requirement doesn’t need to have data or properties.
一个要求不需要有数据或属性。
Authorization Handlers¶ 授权处理器
An authorization handler is responsible for the evaluation of any properties of a requirement. The authorization handler must evaluate them against a provided AuthorizationContext
to decide if authorization is allowed. A requirement can have multiple handlers. Handlers must inherit AuthorizationHandler<T>
where T is the requirement it handles.
授权句处理器负责检查一个要求的所有属性。授权处理器必须按照提供的AuthorizationContext进行检测, 以确定是否允许该项授权。一个要求可有多个处理器。处理器必须引用AuthorizationHandler<T>, 这里的T是所需处理器的泛型。
The minimum age handler might look like this:
最小年龄处理器看起来是这样的:
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;
}
}
In the code above we first look to see if the current user principal has a date of birth claim which has been issued by an Issuer we know and trust. If the claim is missing we can’t authorize so we return. If we have a claim, we figure out how old the user is, and if they meet the minimum age passed in by the requirement then authorization has been successful. Once authorization is successful we call context.Succeed()
passing in the requirement that has been successful as a parameter.
在上面的代码中,我们首先看一下,如果当前的用户规则具有出生日期的声明,该声明由已知的并被信任的机构签发。如果缺少这个声明,我们不能进行授权,进而执行返回操作。如果有一个声明,我们计算出用户的年龄,并且如果年龄符合要求,这样授权检查就成功了。一旦授权成功,就在要求中调用context.Succeed(),并将成功验证作为一个参数。
Handlers must be registered in the services collection during configuration, for example;
处理器必须于配置期间在服务集合中注册,例如:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(); services.AddAuthorization(options =>
{
options.AddPolicy("Over21",
policy => policy.Requirements.Add(new MinimumAgeRequirement()));
}); services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();
}
Each handler is added to the services collection by using services.AddSingleton<IAuthorizationHandler, YourHandlerClass>();
passing in your handler class.
每一个处理器都通过使用services.AddSingleton<IAuthorizationHandler, YourHandlerClass>()被添加进服务集合,传递到处理器类中。
What should a handler return?¶ 一个处理器会返回什么
You can see in our handler example that the Handle()
method has no return value, so how do we indicate success or failure?
可以看到在处理器的例子中,Handle()方法没有返回值,所以我们如何表明成功或者失败呢?
- A handler indicates success by calling
context.Succeed(IAuthorizationRequirement requirement)
, passing the requirement that has been successfully validated. - 一个处理器通过调用context.Succeed(IAuthorizationRequirement requirement)来表示成功,向要求传递已经进行了成功验证的信息。
- A handler does not need to handle failures generally, as other handlers for the same requirement may succeed.
- 一般地,一个处理器不需要处理失败信息,因为一个要求的其他处理就会满足条件了。
- To guarantee failure even if other handlers for a requirement succeed, call
context.Fail
. - 如果处理器的其他要求验证成功了,仍要传递验证失败信息,可调用context.Fail
Regardless of what you call inside your handler all handlers for a requirement will be called when a policy requires the requirement. This allows requirements to have side effects, such as logging, which will always take place even if context.Fail()
has been called in another handler.
无论您在您的处理程序中调用什么,当一个策略需要要求时,一个要求的所有处理程序都将会被调用。这使得要求有副作用,例如日志,尽管context.Fail()已在另一个处理程序被调用,它将总会发生。
Why would I want multiple handlers for a requirement?¶
为什么我需要一个复合处理器?
In cases where you want evaluation to be on an OR basis you implement multiple handlers for a single requirement. For example, Microsoft has doors which only open with key cards. If you leave your key card at home the receptionist prints a temporary sticker and opens the door for you. In this scenario you’d have a single requirement, EnterBuilding, but multiple handlers, each one examining a single requirement.
当需要检测“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;
}
}
Now, assuming both handlers are registered when a policy evaluates the EnterBuildingRequirement
if either handler succeeds the policy evaluation will succeed.
现在,假定两个处理器都被注册了,当这个策略检查EnterBuildingRequirement 时,如果每个处理器都会成功验证。
Using a func to fufill a policy¶ 使用函数满足策略
There may be occasions where fufilling a policy is simple to express in code. It is possible to simply supply a Func<AuthorizationHandlerContext, bool>
when configuring your policy with the RequireAssertion
policy builder.
有这种场合,用代码表达一个策略是简单的。这个功能可以这样来实现,当用RequireAssertion 策略构造器配置策略时,简单地提供一个Func<AuthorizationHandlerContext, bool> 。
For example the previous BadgeEntryHandler
could be rewritten as follows;
举一个例子,前面的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"));
}));
}
}
Accessing MVC Request Context In Handlers¶ 在处理器中使用MVC请求上下文
The Handle
method you must implement in an authorization handler has two parameters, an AuthorizationContext
and the Requirement
you are handling. Frameworks such as MVC or Jabbr are free to add any object to the Resource
property on the AuthorizationContext
to pass through extra information.
在授权处理器中必须引用的Handle方法有两个参数,一个是AuthorizationContext ,另一个是你正在处理的Requirement 。诸如MVC或者Jabbr等框架是开放的,可以向AuthorizationContext的Resource属性添加任何对象,以传递特别的信息。
For example MVC passes an instance of Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext
in the resource property which is used to access HttpContext, RouteData and everything else MVC provides.
例如,MVC向resource属性传递了Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext 的一个实例,该实例用于连接HttpContext、RouteData以及MVC提供的其他一切。
The use of the Resource
property is framework specific. Using information in the Resource
property will limit your authorization policies to particular frameworks. You should cast the Resource
property using the as
keyword, and then check the cast has succeed to ensure your code doesn’t crash with InvalidCastExceptions
when run on other frameworks;
使用Resource 属性是由框架指定的。使用Resource属性中的信息将限制你的授权策略至特殊的框架。你将使用as关键字注入Resource特性,并且检测注入已经成功,来保证代码运行到其他框架时不会遇到InvalidCastExceptions 而崩溃。
var mvcContext = context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext; if (mvcContext != null)
{
// Examine MVC specific things like routing data.
}
&lt;img alt="" width="1" height="1" src="https://c.microsoft.com/trans_pixel.aspx"/&gt;
Security » Authorization » 基于自定义策略的授权的更多相关文章
- Security » Authorization » 基于声明的授权
Claims-Based Authorization¶ 基于声明的授权 142 of 162 people found this helpful When an identity is created ...
- Security » Authorization » 基于资源的授权
Resource Based Authorization¶ 基于资源的授权 68 of 73 people found this helpful Often authorization depends ...
- Security » Authorization » 基于角色的授权
Role based Authorization¶ 基于角色的授权 133 of 153 people found this helpful When an identity is created i ...
- Security » Authorization » 基于视图的授权
View Based Authorization¶ 基于视图的授权 44 of 46 people found this helpful Often a developer will want to ...
- ASP.NET Core的JWT的实现(自定义策略形式验证).md
既然选择了远方,便只顾风雨兼程 __ HANS许 在上篇文章,我们讲了JWT在ASP.NET Core的实现,基于中间件来实现.这种方式有个缺点,就是所有的URL,要嘛需要验证,要嘛不需要验证,没有办 ...
- asp.net core 2.0 web api基于JWT自定义策略授权
JWT(json web token)是一种基于json的身份验证机制,流程如下: 通过登录,来获取Token,再在之后每次请求的Header中追加Authorization为Token的凭据,服务端 ...
- 【JavaEE】SSH+Spring Security自定义Security的部分处理策略
本文建立在 SSH与Spring Security整合 一文的基础上,从这篇文章的example上做修改,或者从 配置了AOP 的example上做修改皆可.这里主要补充我在实际使用Spring Se ...
- gRPC asp.net core自定义策略认证
在GitHub上有个项目,本来是作为自己研究学习.net core的Demo,没想到很多同学在看,还给了很多星,所以觉得应该升成3.0,整理一下,写成博分享给学习.net core的同学们. 项目名称 ...
- Blazor应用程序基于策略的授权
原文:https://chrissainty.com/securing-your-blazor-apps-configuring-policy-based-authorization-with-bla ...
随机推荐
- 判断日期是否符合yyyy-mm格式
!Regex.IsMatch(dr["DMAKEDATE"].ToString(),@"^(?<year>\\d{2,4})-(?<month>\ ...
- LeetCode Patching Array
原题链接在这里:https://leetcode.com/problems/patching-array/ 题目: Given a sorted positive integer array nums ...
- 简单理解php的socket编程
php的socket编程算是比较难以理解的东西吧,不过,我们只要理解socket几个函数之间的关系,以及它们所扮演的角色,那么理解起来应该不是很难了,在笔者看来,socket编程,其实就是建立一个网络 ...
- 循环调用MAIN
--单位转移录入declare oi_errcode integer; oc_errtext varchar2(100);begin for p in (select * from ssunitinf ...
- RW-50004 While Running adrunfmw during EBS 12.2 Installation
安装过程中报错: 日志文件信息: Executing command: /app/R1220/startCD/Disk1/rapidwiz/jre/Linux_x64//bin/java -cp /a ...
- Web3D编程总结——3D碰撞检测初探
自己动手写一个方法比分析他人的写的方法困难很多,由此而来的对程序的进一步理解也是分析别人的代码很难得到的. 一.先来几张效果图: 1.场景中有两个半径为1的球体,蓝色线段从球心出发指向球体的“正向” ...
- POJ 2104 K-th Number(主席树——附讲解)
Description You are working for Macrohard company in data structures department. After failing your ...
- JVM参数设置、分析(转发)
JVM参数的含义 实例见实例分析 参数名称 含义 默认值 -Xms 初始堆大小 物理内存的1/64(<1GB) 默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,J ...
- Monkey之环境搭建完全版
图文版将在后期补充. 如果想要搭建好Monkey的测试环境,首先几个必要的步骤和环境不能少,分别是java相关环境.Android SDK环境,启动android虚拟机或连接真机.执行monkey测试 ...
- viewpager实现酷炫侧滑demo
晚上叫外卖,打开饿了么,发现推了一个版本,更新以后,点开了个鸡腿,哇,交互炫炸了. 不过还是有槽点.我是无意中才发现可以左右滑动的.这...你不告诉我,我怎么知道左右可以滑. https://gith ...