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和 ...
随机推荐
- BZOJ 1061: [Noi2008]志愿者招募 [单纯形法]【学习笔记】
1061: [Noi2008]志愿者招募 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 3975 Solved: 2421[Submit][Stat ...
- Python3实现TCP端口扫描
在渗透测试的初步阶段通常我们都需要对攻击目标进行信息搜集,而端口扫描就是信息搜集中至关重要的一个步骤.通过端口扫描我们可以了解到目标主机都开放了哪些服务,甚至能根据服务猜测可能存在某些漏洞. TCP端 ...
- block的哪些事 --- 学习笔记十
//带有自动变量值的匿名函数 //block 与 C语言函数比只有两点不同,1.没有函数名. 2.带有"^". //类似于方法,如B中的值传给A中,在B中,一. 定义 : 二. 实 ...
- BZOJ 4423 【AMPPZ2013】 Bytehattan
Description 比特哈顿镇有n*n个格点,形成了一个网格图.一开始整张图是完整的. 有k次操作,每次会删掉图中的一条边(u,v),你需要回答在删除这条边之后u和v是否仍然连通. Input 第 ...
- java并发编程学习: ThreadLocal使用及原理
多线程应用中,如果希望一个变量隔离在某个线程内,即:该变量只能由某个线程本身可见,其它线程无法访问,那么ThreadLocal可以很方便的帮你做到这一点. 先来看一下示例: package yjmyz ...
- 基于jquery的has()方法以及与find()方法以及filter()方法的区别详解
has(selector选择器或DOM元素) 将匹配元素集合根据选择器或DOM元素为条件,检索该条件在每个元素的后代中是否存在,将符合条件的的元素构成新的结果集. 下面举一个例子: <ul& ...
- <转>打工与乘公交
打工与乘公交 去一个公司打工就如同上了一辆公交车.在上车之前,你应该清楚自己打算去哪里,打算在哪里下车. 有的公交车很豪华,有的很破烂,但是这并不是重点,所有能开到目的地的车都是好车. 上了车之后,也 ...
- [word]用Word2007查找和替换功能批量设置图片位置
Word2007的"查找和替换"功能并不仅仅可以对文字进行批量的查找替换,还有很多神奇的功能,比如对插入的图片位置进行批量的查找和调整等等. 今天我们就来试试Word2007的&q ...
- Apache Shiro系列三,概述 —— 10分钟入门
一.介绍 看完这个10分钟入门之后,你就知道如何在你的应用程序中引入和使用Shiro.以后你再在自己的应用程序中使用Shiro,也应该可以在10分钟内搞定. 二.概述 关于Shiro的废话就不多说了 ...
- Spring IOC容器创建对象的方式
一.无参构造函数创建 我们用Spring创建Stu ...