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和 ...
随机推荐
- QuickHit项目(输出字符串游戏)
public class leve { private int leveNo; private int strLength; private int strTimes; private int tim ...
- 洛谷P1119 灾后重建[Floyd]
题目背景 B地区在地震过后,所有村庄都造成了一定的损毁,而这场地震却没对公路造成什么影响.但是在村庄重建好之前,所有与未重建完成的村庄的公路均无法通车.换句话说,只有连接着两个重建完成的村庄的公路才能 ...
- Java的泛型反射
If the superclass is a parameterized type, the {@code Type} * object returned must accurately reflec ...
- bash 脚本编程 利用 “=” 赋值时,左右不能留空格
对脚本变量用“=”赋值时, "=" 左右不能留有空格,否则会提示错误. 比如以下例子: #!/bin/bash BEGIN_TIME = `date +%H:%M:%S` ./a. ...
- Mysql完全手册(笔记一,底层与内置函数)
1.MySQL由五个主子系统组成.协同工作,这五个主子系统是: (1)查询引擎 (2)存储管理器 (3)缓冲管理器 (4)事务管理器 (5)恢复管理器 查询引擎: 这个子系统包含三个相互关联的部件: ...
- asp.net core 部署 提示DataProtectionServices 错误
今天在部署asp.net core网站时,因为调用到阿里云的api,api的参数需要加密签名,系统报出了如下错误: warn: Microsoft.Extensions.DependencyInjec ...
- 转 android 从底部弹出一个popuwindow,渐入渐出效果。我这里是用在购物车需要选择购买选项的操作。
最近要改客户端,需要实现一个从底部弹出的popuwindow,像我这种渣渣android技术,能整出popuwindow但是整不出动画,百度之,记录一下. 从下面这个地址转的 http://blog. ...
- C#进阶系列——MEF实现设计上的“松耦合”(四):构造函数注入
前言:今天十一长假的第一天,本因出去走走,奈何博主最大的乐趣是假期坐在电脑前看各处堵车,顺便写写博客,有点收获也是好的.关于MEF的知识,之前已经分享过三篇,为什么有今天这篇?是因为昨天分享领域服务的 ...
- Jquery遮罩插件,想罩哪就罩哪!
一 前言 在项目开发时发现没有一个用起来 爽一点的遮罩插件,看起来觉得不难 好吧那就利用空闲时间,自己折腾一个吧,也好把jquery再温习一下, 需要的功能如下 1 可以全屏遮 用于提交数据时 2 ...
- Visual Studio 2015的坑:中文字符串编译后成乱码
(2015年8月5日更新:微软已经修复了Roslyn的这个bug,详见 https://github.com/dotnet/roslyn/pull/4303 ) 昨天,我们用VS2015编译了博客程序 ...