.Net Core Policy 基于策略授权

        在ASP.NET Core中,重新设计了一种更加灵活的授权方式:基于策略的授权, 它是授权的核心.在使用基于策略的授权时,首先要定义授权策略,而授权策略本质上就是对Claims的一系列断言。基于角色的授权和基于Scheme的授权,只是一种语法上的便捷,最终都会生成授权策略。

public void ConfigureServices(IServiceCollection services)
{services.AddMvc();services.AddAuthorization(options =>{//options.AddPolicy("Administrator", policy => policy.RequireRole("administrator"));options.AddPolicy("Administrator", policy => policy.RequireClaim(ClaimTypes.Role, "administrator"));//options.AddPolicy("Founders", policy => policy.RequireClaim("EmployeeNumber", "1", "2", "3", "4", "5"));});
}
[Authorize(Policy = "Administrator")]
public ActionResult<IEnumerable<string>> GetValueByAdminPolicy()
{return new string[] { "GetValueByAdminPolicy" };
}

自定义策略授权

        基于策略的授权中有一个很重要的概念是Requirements,每一个Requirement都代表一个授权条件。Requirement需要继承接口IAuthorizationRequirement。
在 ASP.NET Core 中已经内置了一些常用的实现:

AssertionRequirement :使用最原始的断言形式来声明授权策略。
DenyAnonymousAuthorizationRequirement :用于表示禁止匿名用户访问的授权策略,并在AuthorizationOptions中将其设置为默认策略。
ClaimsAuthorizationRequirement :用于表示判断Cliams中是否包含预期的Claims的授权策略。
RolesAuthorizationRequirement :用于表示使用ClaimsPrincipal.IsInRole来判断是否包含预期的Role的授权策略。
NameAuthorizationRequirement:用于表示使用ClaimsPrincipal.Identities.Name来判断是否包含预期的Name的授权策略。
OperationAuthorizationRequirement:用于表示基于操作的授权策略。
        除了OperationAuthorizationRequirement外,都有对应的快捷添加方法,比如RequireClaim,RequireRole,RequireUserName等。当内置的Requirement不能满足需求时,可以定义自己的Requirement。

下面演示自定义策略授权

Startup类配置

 // This method gets called by the runtime. Use this method to add services to the container.public void ConfigureServices(IServiceCollection services){services.AddAuthorization(options =>{options.AddPolicy("Permission", policy => policy.Requirements.Add(new PermissionRequirement()));}).AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>{options.LoginPath = new PathString("/api/values/login");});services.AddTransient<IUserService, UserService>();services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();services.AddSingleton<IAuthorizationHandler, PermissionHandler>();services.AddControllers();}

 Configure方法添加

app.UseAuthentication();
app.UseAuthorization();

新建类 PermissionRequirement 

  public class PermissionRequirement : IAuthorizationRequirement{}

新建类 PermissionHandler 

public class PermissionHandler : AuthorizationHandler<PermissionRequirement>{private readonly IUserService _userService;private readonly IHttpContextAccessor _accessor;public PermissionHandler(IUserService userService, IHttpContextAccessor accessor){_userService = userService;_accessor = accessor;}protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement){var httpContext = _accessor.HttpContext;var isAuthenticated = httpContext.User.Identity.IsAuthenticated;if (isAuthenticated){Guid userId;if (!Guid.TryParse(httpContext.User.Claims.SingleOrDefault(s => s.Type == "id").Value, out userId)){return Task.CompletedTask;}var functions = _userService.GetFunctionsByUserId(userId);var requestUrl = httpContext.Request.Path.Value.ToLower();if (functions != null && functions.Count > 0 && functions.Contains(requestUrl)){context.Succeed(requirement);}}return Task.CompletedTask;}}

 添加测试用户数据,项目中需从数据库读取

public static class TestUsers{public static List<User> Users = new List<User>{new User{ Id = Guid.NewGuid(), UserName = "Paul", Password = "Paul123", Roles = new List<string>{ "administrator", "api_access" }, Urls = new List<string>{ "/api/values/getadminvalue", "/api/values/getguestvalue" }},new User{ Id = Guid.NewGuid(), UserName = "Young", Password = "Young123", Roles = new List<string>{ "api_access" }, Urls = new List<string>{ "/api/values/getguestvalue" }},new User{ Id = Guid.NewGuid(), UserName = "Roy", Password = "Roy123", Roles = new List<string>{ "administrator" }, Urls = new List<string>{ "/api/values/getadminvalue" }},};}public class User{public Guid Id { get; set; }public string UserName { get; set; }public string Password { get; set; }public List<string> Roles { get; set; }public List<string> Urls { get; set; }}

 添加UserService

public interface IUserService{List<string> GetFunctionsByUserId(Guid id);}
 public class UserService : IUserService{public List<string> GetFunctionsByUserId(Guid id){var user = TestUsers.Users.SingleOrDefault(r => r.Id.Equals(id));return user?.Urls;}}

添加api类

[Authorize(Policy = "Permission")][Route("api/[controller]")][ApiController]public class ValuesController : ControllerBase{[HttpGet("[action]")]public ActionResult<IEnumerable<string>> GetAdminValue(){return new string[] { "use Policy = Permission" };}[HttpGet("[action]")]public ActionResult<IEnumerable<string>> GetGuestValue(){return new string[] { "use Policy = Permission" };}[AllowAnonymous][HttpPost("[action]")]public async Task<ActionResult<bool>> Login([FromBody]UserDto dto){var user = TestUsers.Users.FirstOrDefault(s => s.UserName == dto.UserName && s.Password == dto.Password);if (user != null){//用户标识var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);identity.AddClaim(new Claim(ClaimTypes.Sid, user.UserName));identity.AddClaim(new Claim("id", user.Id.ToString()));await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity));if (dto.ReturnUrl != null){return Redirect(dto.ReturnUrl);}else{return RedirectToAction(nameof(ValuesController.GetAdminValue), "Values");}}else{const string badUserNameOrPasswordMessage = "用户名或密码错误!";return BadRequest(badUserNameOrPasswordMessage);}}public class UserDto{public string UserName { get; set; }public string Password { get; set; }public string ReturnUrl { get; set; }}}

        然后我们用Paul用户可以访问所有的接口,Young只能访问getguestvalue接口,Roy只能访问getadminvalue接口。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/655822.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学废SpringBoot+Redis+Lua=王炸(值得珍藏)

1. Lua语言 1.1 Lua简介 Lua是一种轻量级、可嵌入的脚本语言&#xff0c;广泛应用于游戏开发、Web开发和其他领域。其简洁的语法和强大的功能使其成为一种高效、易用的编程语言。Lua语言的设计原则是提供一种易于学习、易于使用且具有强大功能的语言&#xff0c;让程序员能够…

计网Lesson11 - 虚拟机网络环境及socket概述

文章目录 虚拟机的简述socket概述 虚拟机的简述 放张图在这&#xff0c;根本没明白是啥对啥&#xff0c;以后学了Linux再来吧 &#x1f626; socket概述 s o c k e t socket socket 是一种用于应用层的用户态与应用层以下的内核态交互的工具&#xff0c;本意为“插座”。 也就是…

MySQL常用关键字

MySQL常用关键字 目录 MySQL常用关键字DDL关键字DML关键字DQL关键字DCL关键字约束关键字 DDL关键字 DDL关键字含义CREATE TABLE创建一个新的数据库表ALTER TABLE修改现有数据库表的结构或属性DROP TABLE删除数据库中的表MODIFY COLUMN修改列ADD COLUMN新增列CREATE INDEX创建索…

HarmonyOS NEXT 星河版项目案例

参考代码&#xff1a;HeimaHealthy: 鸿蒙项目案例练习 (gitee.com) 1.欢迎页面 Entry Component struct WelcomePage {State message: string Hello Worldbuild() {Column({space: 10}) {Row() {// 1.中央slogonImage($r(app.media.home_slogan)).width(260)}.layoutWeight(…

FL Studio21.2.2中文完整版 适合专业创作者

FL Studio 简称FL&#xff0c;全称&#xff1a;Fruity Loops Studio&#xff0c;因此国人习惯叫它"水果"。目前版本是FL Studio2024&#xff0c;它让你的计算机就像是全功能的录音室&#xff0c;大混音盘&#xff0c;非常先进的制作工具&#xff0c;让你的音乐突破想…

GD32F30x SPI转CAN 从机实现

SPI 转CAN 目前常用MCP251x 年代较远&#xff0c;目前多数MCU 自带CAN 模块和SPI 主从模块&#xff0c;很方便实现SPI 转CAN 串口等外设&#xff0c;可用作linux 主机下的一个驱动外设&#xff1b; SPI通信不同于串口等全双工通信&#xff0c;主机在发送数据的同时也能得到从机…

分布式虚拟文件系统,如何实现多种存储系统的融合

随着大数据技术和人工智能技术的发展&#xff0c;各种框架应运而生&#xff0c;比如大数据领域中的MapReduce和Spark&#xff0c;人工智能领域中的TensorFlow和PyTorch等。为了给不同的计算框架提供存储服务&#xff0c;存储的服务类型也是很多&#xff0c;常见的如AWS的S3存储…

winform工具报错处理

winform工具报错处理 如图&#xff1a; 出现这种错误&#xff0c;工具打不开就是没有这个&#xff08;.NET&#xff09;环境&#xff0c;需要根据工具的使用开发环境安装配置插件 解决方案 需要安装如图的插件&#xff1a; 选择文件导入报错 1.如果之前已安装过AccessDat…

【c++】日期类的实现-Class Date

代码实现 #define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> using namespace std; class Date { public:// 获取某年某月的天数int GetMonthDay(int year, int month){static int monteDays[13] { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (month 2 &&…

Properties 文件顺序读取问题

我们通常会使用 Properties 去读取 properties 文件的内容&#xff0c;但 Properties 的问题是无法按照 properties 文件的顺序去读取。因为 Properties 继承自Hashtable&#xff0c;是一个基于哈希表的数据结构&#xff0c;元素的存储位置是通过元素的键的哈希值计算出来的&am…

[React源码解析] Fiber (二)

在React15及以前, Reconciler采用递归的方式创建虚拟Dom, 但是递归过程不可以中断, 如果组件的层级比较深的话, 递归会占用线程很多时间, 那么会造成卡顿。 为了解决这个问题, React16将递归的无法中断的更新重构为异步的可中断更新, Fiber架构诞生。 文章目录 1.Fiber的结构2…

Android Studio项目——TCP客户端

目录 一、TCP客户端UI 1、UI展示 2、xml代码 二、TCP客户端数据发送 三、TCP客户端数据接收 一、TCP客户端UI 1、UI展示 2、xml代码 <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.…

【LeetCode】617. 合并二叉树(简单)——代码随想录算法训练营Day20

题目链接&#xff1a;617. 合并二叉树 题目描述 给你两棵二叉树&#xff1a; root1 和 root2 。 想象一下&#xff0c;当你将其中一棵覆盖到另一棵之上时&#xff0c;两棵树上的一些节点将会重叠&#xff08;而另一些不会&#xff09;。你需要将这两棵树合并成一棵新二叉树。…

开始一个vue项目

一、新建项目 用cmd命令创建项目 1.1创建文件 以管理员身份打开命令行界面&#xff0c;进入任意一个想要创建项目的文件夹 输入&#xff1a;vue create vue01 1.2创建成功 Successfully created project vue01出现这个说明创建成功1.3项目目录 二、 vue-router 安装和配置的…

C语言-动态内存申请

一、动态分配内存的概述 在数组一章中&#xff0c;介绍过数组的长度是预先定义好的&#xff0c;在整个程序中固定不变&#xff0c;但是在实际的编程中&#xff0c;往往会发生这种情况&#xff0c;即所需的内存空间取决于实际输入的数据&#xff0c;而无法预先确定 。为了解决…

ChatGPT PLUS升级步骤--支付宝、微信

AI伴随着我们已经有一年多了&#xff0c;这一年多里我使用ChatGPT做ppt、生成绘画、写文案、做旅游攻略&#xff0c;还有一些医学知识&#xff0c;医学知识我感觉没有回答的很好&#xff0c;对比于医生给的建议我个人觉得还是医生的比较好&#xff0c;Chat GPT回答的比较官方 …

AWS免费套餐——云存储S3详解

文章目录 前言一、为什么选择S3二、费用估算三、创建S3云存储注册账户登录账户创建存储桶关于官网相关文档 总结 前言 不论个人还是企业&#xff0c;日常开发中经常碰到需要将文档、安装包、日志等文件数据存储到服务器的需求。往常最常用的是云服务器&#xff0c;但是仅仅承担…

leetcode hot100跳跃游戏Ⅱ

本题和上一题还是有不一样的地方&#xff0c;这个题中&#xff0c;我们需要记录我们跳跃的步数并尽可能的满足最小的跳跃步数到达终点。 那么我们还是采用覆盖范围的概念&#xff0c;但是我们需要两个&#xff0c;一个是在当前位置的覆盖范围&#xff0c;另一个是下一步的覆盖…

gerrit 2 升级到 3最新版本(2.16-->3.9.1)--官方升级方式

root用户安装jdk11 和 17 # 11.0.21 支持到gerrit 3.8&#xff0c;gerrit 3.9 得需要 17 [rootlocalhost ~]# cd /usr/local/java/ [rootlocalhost java]# wget https://mirrors.xingyunkeji.com/package/jdk/openjdk-11.0.21%2B9-linux-x64.tar.gz [rootlocalhost java]# wge…

分布式系统面试的秘籍:深入探讨事务、幂等性和补偿事务,掌握二/三阶段提交,了解Sagas事务模型和分布式ID的实战应用!

1、分布式幂等性如何设计&#xff1f;并举例说明 设计分布式系统的幂等性是确保在面对重复请求或操作时系统能够产生相同结果的重要方面。以下是一些设计方法&#xff0c;并结合一个简单的例子说明&#xff1a; 设计方法&#xff1a; 唯一标识符&#xff08;ID&#xff09;:…