.NET6之MiniAPI(十):基于策略的身份验证和授权

JWT不管是基于角色,还是自定义策略,实现的步骤都是大同小异的,基于自定义策略的步骤如下:

1、appsettings.json中配置JWT参

2、添加身份认证和授权服务和中间件,并设置为策略模式和策略名称

3、定义生成Token的方法和验证Toekn参数的方法

4、登录时验证身份并分发Toekn

5、继承AuthorizationHandler<IAuthorizationRequirement>,实现鉴权的规则

接下来看看具体实现。

JWT配置

"JWTConfig": {"Secret": "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890","Issuer": "gsw","Audience": "everone","Expires": 10000}

实现自定义策略

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;var builder = WebApplication.CreateBuilder();
//绑定JWT配置文年
var jwtConfig = new JWTConfig();
builder.Configuration.GetSection("JWTConfig").Bind(jwtConfig);
builder.Services.AddSingleton(jwtConfig);
//这里是注入权限数据,也可以放在缓存中,以便鉴权时用
builder.Services.AddSingleton(new List<Permission> { new Permission { RoleName = "admin", Url = "/helloadmin", Method = "get" } });
//注入自定义策略处理类型
builder.Services.AddSingleton<IAuthorizationHandler, PermissionHandler>();
//注入身分验证和授权,并且是Policy的名称为Permission
builder.Services.AddAuthorization(options =>{var permissionRequirement = new PermissionRequirement();options.AddPolicy("Permission", policy => policy.AddRequirements(permissionRequirement));}).AddAuthentication(options =>{options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, opt =>{opt.RequireHttpsMetadata = false;opt.TokenValidationParameters = JwtToken.CreateTokenValidationParameters(jwtConfig);});var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
//map三个get请求,都是.RequireAuthorization("Permission"),基于Permission策略来验证的
app.MapGet("/hellosystem", (ILogger<Program> logger, HttpContext context) =>
{var message = $"hello,system,{context.User?.Identity?.Name}";logger.LogInformation(message);return message;
}).RequireAuthorization("Permission");app.MapGet("/helloadmin", (ILogger<Program> logger, HttpContext context) =>
{var message = $"hello,admin,{context.User?.Identity?.Name}";logger.LogInformation(message);return message;
}).RequireAuthorization("Permission");app.MapGet("/helloall", (ILogger<Program> logger, HttpContext context) =>
{var message = $"hello,all roles,{context.User?.Identity?.Name}";logger.LogInformation(message);return message;
}).RequireAuthorization("Permission");//登录,并分发Token
app.MapPost("/login", [AllowAnonymous] (ILogger<Program> logger, LoginModel login, JWTConfig jwtConfig) =>
{logger.LogInformation("login");if (login.UserName == "gsw" && login.Password == "111111"){var now = DateTime.UtcNow;var claims = new Claim[] {new Claim(ClaimTypes.Role, "admin"),new Claim(ClaimTypes.Name, "桂素伟"),new Claim(ClaimTypes.Sid, login.UserName),new Claim(ClaimTypes.Expiration, now.AddSeconds(jwtConfig.Expires).ToString())};var token = JwtToken.BuildJwtToken(claims, jwtConfig);return token;}else{return "username or password is error";}
});app.Run();
//登录实体
public class LoginModel
{public string? UserName { get; set; }public string? Password { get; set; }
}
//JWT配置文年
public class JWTConfig
{public string? Secret { get; set; }public string? Issuer { get; set; }public string? Audience { get; set; }public int Expires { get; set; }
}
//Token功能类
public class JwtToken
{public static dynamic BuildJwtToken(Claim[] claims, JWTConfig jwtConfig){var now = DateTime.UtcNow;var jwt = new JwtSecurityToken(issuer: jwtConfig.Issuer,audience: jwtConfig.Audience,claims: claims,notBefore: now,expires: now.AddSeconds(jwtConfig.Expires),signingCredentials: GetSigningCredentials(jwtConfig));var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);var response = new{Status = true,AccessToken = encodedJwt,ExpiresIn = now.AddSeconds(jwtConfig.Expires),TokenType = "Bearer"};return response;}static SigningCredentials GetSigningCredentials(JWTConfig jwtConfig){var keyByteArray = Encoding.ASCII.GetBytes(jwtConfig?.Secret!);var signingKey = new SymmetricSecurityKey(keyByteArray);return new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);}public static TokenValidationParameters CreateTokenValidationParameters(JWTConfig jwtConfig){var keyByteArray = Encoding.ASCII.GetBytes(jwtConfig?.Secret!);var signingKey = new SymmetricSecurityKey(keyByteArray);return new TokenValidationParameters{ValidateIssuerSigningKey = true,IssuerSigningKey = signingKey,ValidateIssuer = true,ValidIssuer = jwtConfig?.Issuer,ValidateAudience = true,ValidAudience = jwtConfig?.Audience,ClockSkew = TimeSpan.Zero,RequireExpirationTime = true,};}
}
//权限实本类
public class Permission
{public string? RoleName { get; set; }public string? Url { get; set; }public string? Method { get; set; }
}
//自定义策略授权时的参数类型,这时没参数,所以是个空类型
public class PermissionRequirement : IAuthorizationRequirement
{
}
//自定义策略授权的处理类型
public class PermissionHandler : AuthorizationHandler<PermissionRequirement>
{private readonly List<Permission> _userPermissions;public PermissionHandler(List<Permission> permissions){_userPermissions = permissions;}protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement){if (context.Resource is DefaultHttpContext){var httpContext = context.Resource as DefaultHttpContext;var questPath = httpContext?.Request?.Path;var method = httpContext?.Request?.Method;var isAuthenticated = context?.User?.Identity?.IsAuthenticated;if (isAuthenticated.HasValue && isAuthenticated.Value){var role = context?.User?.Claims?.SingleOrDefault(s => s.Type == ClaimTypes.Role)?.Value;if (_userPermissions.Where(w => w.RoleName == role && w.Method?.ToUpper() == method?.ToUpper() && w.Url?.ToLower() == questPath).Count() > 0){context?.Succeed(requirement);}else{context?.Fail();}}}return Task.CompletedTask;}
}

运行结果如下:

1、没有登录,返回401

8185df843f7d40e3acc6abae2f8df2ce.png

2、登录,取token

4ba699c681b7fd28cdf0095b8371d130.png

3、正确访问

e4fbff00e81040af4c54aa5d29887c82.png

4、没有授权访问,返回403

47e53f92c61309e90f15b70f291e6297.png

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

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

相关文章

架构设计:远程调用服务架构设计及zookeeper技术详解(上篇)

一、序言 Hadoop是一个技术生态圈&#xff0c;zookeeper是hadoop生态圈里一个非常重要的技术&#xff0c;当我研究学习hadoop的相关技术时候&#xff0c;有两块知识曾经让我十分的困惑&#xff0c;一个是hbase&#xff0c;一个就是zookeeper&#xff0c;hbase的困惑源自于它在颠…

据说很多女生都想知道男生是如何上厕所的?

1 老婆守恒定律&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼2 捡破烂的狗子&#xff08;via.李市民&#xff0c;侵删&#xff09;▼3 见过最搞笑的买药经历&#xff08;素材来源豆瓣yuyii&#xff0c;侵删&#xff09;▼4 男朋友的室友可以多粘人&#xff1f;&a…

【云图】如何设置支付宝里的家乐福全国连锁店地图?

【云图】如何设置支付宝里的家乐福全国连锁店地图&#xff1f; 原文:【云图】如何设置支付宝里的家乐福全国连锁店地图&#xff1f; 摘要&#xff1a;本文详细讲解了&#xff0c;如何设置支付宝服务窗。商家如何将自己的全国连锁店放置到云图上&#xff0c;并且在支付宝服务窗中…

ABP vNext微服务架构详细教程——基础服务层

1服务创建在除身份管理相关服务以外的其他业务服务中&#xff0c;我们不需要包含用户角色权限管理功能模块&#xff0c;ABP vNext框架为我们提供了模块模式&#xff0c;其默认模板不包含身份管理相关模块&#xff0c;更适合用于搭建普通的业务微服务。以产品管理服务为例&#…

中国第一个发《Nature》的竟然是清朝人!被皇帝夸天下第一,他却觉得羞耻..........

全世界只有3.14 % 的人关注了爆炸吧知识大清亡了&#xff01;这事在今天讲&#xff0c;算不得惊天动地&#xff0c;你听了之后&#xff0c;还可能微微一笑。作为中国最后一个封建王朝&#xff0c;它先闭关锁国&#xff0c;后又丧权辱国&#xff0c;造成百年前的中国在科学技术方…

码农与UI沟通的日常

事情是这样的&#xff0c;这是一个兴趣群组的效果图。 我看了一眼没有帖子时的提示&#xff0c;觉得这样的提示 不走心 不能展现出我们团队对于人生及世界的深度理解和高尚的品格。 于是&#xff0c;我选择了表达内心的真实感受。 我觉得这完美表达了用户使用时的心声&#xff…

贝叶斯分类器_Sklearn 中的朴素贝叶斯分类器

(给Python开发者加星标&#xff0c;提升Python技能)作者&#xff1a;Martin Mller&#xff0c;翻译&#xff1a;github-sisibelovedhttps://github.com/xitu/gold-miner/blob/master/TODO1/naive-bayes-classifier-sklearn-python-example-tips.md用豆机实现的高斯分布这篇教程…

linux之tr命令使用和总结

1、tr命令介绍 用来从标准输入中通过替换或删除操作进行字符转换。tr主要用于删除文件中控制字符或进行字符转换。使用tr时要转换两个字符串:字符串1用于查询,字符串2用于处理各种转换。tr刚执行时,字符串1中的字符被映射到字符串2中的字符,然后转换操作开始。 带有最常用…

美少女什么味??竟然还有美少女风味泡面......

1 毕业后第一次参加聚餐&#xff08;via&#xff1a;刘燕铭&#xff09;▼2 建议使用摩斯密码&#xff0c;谢谢▼3 隆马戏&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼4 真的很谢谢▼5 啊&#xff0c;哪里买呢&#xff08;via&#xff1a;Zero 浅忆&#xff09;…

ABP vNext微服务架构详细教程——身份管理服务

1框架搭建ABP vNext创建包含app和module两种模板&#xff0c;其中app方式所创建的模板包含用户、角色、权限管理&#xff0c;ABP基础配置IdentityServer的基础配置数据等功能。module模式是一个比较干净的服务&#xff0c;里面不包含默认业务功能。ABP vNext创建包含app和modul…

双网卡上网冲突解决_【技术文章】局域网IP地址冲突罪魁祸首是什么?这几点要注意!(附高手处理方法)...

现如今&#xff0c;人们的生活处处离不开网络。单位办公信息化对网络的依赖则更大。为了提升安全管理和信息化水平&#xff0c;很多单位不仅建设了完善的办公信息系统&#xff0c;还部署了视频监控。但由于缺乏整体规划&#xff0c;或选择网络产品时考虑欠周&#xff0c;导致网…

异常分析

一、请阅读并运行AboutException.java示例&#xff0c;然后通过后面的几页PPT了解Java中实现异常处理的基础知识。 &#xff08;1&#xff09;源代码;import javax.swing.*; class AboutException { public static void main(String[] a) { int i1, j0, k; ki/j; try { k i/j…

linux c之wait和waitpid函数的用法和总结

1、wait和waitpid函数的介绍 1) wait()函数用于使父进程(也就是调用wait()的进程)阻塞,直到一个子进程结束或者该进程接收到了一个指定的信号为止。如果该父进程没有子进程或者它的子进程已经结束,则wait()函数就会立即返回。 2) waitpid()的作用和wait()一样,但它并不一…

微软开发者的年度回顾

2021 年 .NET 和 Microsoft 开发人员的技术都发生了什么&#xff1f;很难从 2021 年只选择一个主题。安静的进化&#xff1f;开源的争议&#xff1f;一个让开发人员疑惑的操作系统更新&#xff1f;当我回头看时, 发现一年发生了很多事情, 2021 年的发展是稳步向前的&#xff0c…

我是永远不可能出轨的,除非......

1 当爸妈学会了抠图&#xff08;素材来源豆瓣&#xff0c;侵删&#xff09;▼2 帮我带瓶我平时常喝的水&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼3 我们是被资本凑在一起的联姻&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼4 我是不会出轨的&…

linux之学习linux系统相关的书籍

1.《鸟哥的Linux私房菜-基础学习篇》 2.《Linux Shell 脚本攻略》 3.《Unix环境高级编程》 4.《Linux系统编程》

16岁上大学,25岁博士毕业,她还是南大医学院最年轻的博导!

全世界只有3.14 % 的人关注了爆炸吧知识本文转自&#xff1a;募格学术魏嘉&#xff0c;16岁考上南大&#xff0c;25岁博士毕业&#xff0c;是南大医学院最年轻的博导&#xff0c;已在J Natl Cancer Inst等国际著名杂志上发表64篇SCI论文。在第24届“中国青年五四奖章”入围名单…

十年整理CAD精髓

为什么80%的码农都做不了架构师&#xff1f;>>> AUTOCAD使用心得之一 使用的三个基本方面&#xff1a;清晰、准确、高效 目前&#xff0c;公司的设计文件&#xff0c;特别是图纸&#xff0c;都是用AUTOCAD软件绘制的。但是&#xff0c;现在还有很多人对CAD并不是…

使用这个库,让你的服务操作 Redis 速度飞起

点击上方蓝字关注 &#x1f446;&#x1f446;没领红包封面的可以在文末领取大多数人使用 Redis 作为远程缓存存储&#xff0c;因为它速度快。Redis6 通过消除不必要的网络往返&#xff0c;可以使其更快。服务器辅助的客户端缓存这个方法很简单。Redis6 会记录客户端请求的键值…

mysql bigint转string_无语了,直到今天,我才揪出MySQL磁盘消耗迅猛的“真凶”!...

作者&#xff1a;dbapower链接&#xff1a;https://blog.51cto.com/suifu/2135599背景Part1:写在最前当一张单表10亿数据量的表放在你面前&#xff0c;你将面临着什么&#xff1f;Part2:背景介绍为了提升数据库资源利用率&#xff0c;一个实例中&#xff0c;在不互相影响&#…