[鉴权/授权].Net6下Jwt与RefreshToken的结合

微信公众号:趣编程ACE
关注可了解.NET日常开发技巧。如需源码,请公众号留言 源码;

上文回顾

【鉴权/授权】一步一步实现一个简易JWT鉴权

【鉴权/授权】自定义一个身份认证Handler

【鉴权/授权】基于角色的简单授权认证

如何基于JWT实现RefreshToken

在前面的几篇文章中,我一点一点分享了如何利用JWT鉴权、自定义鉴权、基于角色的授权等知识点,如果想了解的请参阅上文回顾
今天这篇文章将分享如何在.net6项目下生成并利用refreshToken进行身份鉴权,亲测可用。。。。素来围观。。。。

创建RefreshToken

1    /// <summary>2    /// 生成refreshToken的接口3    /// </summary>4    public interface IGenerateRefreshToken5    {6        string GenerateRefreshTokenStr();7    }89    /// <summary>
10    /// 生成RefreshToken的接口实例 
11    /// </summary>
12    public class GenerateRefreshTokenImpl: IGenerateRefreshToken
13    {
14        /// <summary>
15        /// 生成32位随机字符的refreshToken
16        /// </summary>
17        /// <returns></returns>
18        public string GenerateRefreshTokenStr()
19        {
20            var refreshBytes = new byte[32];
21            using (var number = RandomNumberGenerator.Create())
22            {
23                number.GetBytes(refreshBytes);
24                return Convert.ToBase64String(refreshBytes);
25            }
26        }
27    }


上面就是一个32位随机字符的refreshToken的接口及其实现方法,有了这个接口服务之后,我们需要在内置的依赖容器里面注入这个服务,于是来到Program.cs文件里面

1// 注入生成refreshToken的服务
2builder.Services.AddSingleton<IGenerateRefreshToken, GenerateRefreshTokenImpl>();

接着我们在登录的逻辑里面除了要生成Token同时也要调用我们上方的refreshToken接口来生成RefreshToken,生成成功后将TokenRefreshToken包裹成一个实体--ResponseModel一并返回给客户端,于是我们来到AuthenticateImpl这个类里面的Login方法。

1            // 生成RefreshToken  其中_generateRefreshToken 是从构造函数中依赖注入进来
2            var refreshToken = _generateRefreshToken.GenerateRefreshTokenStr();
3            // 将refreshToken 缓存起来 这一步可以存到数据库,也可以采用分布式缓存来替代,后续再分享
4            RefreshTokens[userName] = refreshToken;

其中RefreshTokens这个字典类型是这样产生的

1public interface IAuthenticate
2{
3        ResponseModel Login(string userName,string password); // 登录方法
4        Dictionary<string, string> RefreshTokens { get; set; } // refreshToken 缓存
5        ResponseModel Refresh(string userName, RefreshDto refreshDto);  // token失效后刷新方法
6}

然后AuthenticateImpl.cs方法实现这个属性。

Token失效后的Refresh方法(核心逻辑)

1[AllowAnonymous]
2[HttpPost("refresh")]
3public IActionResult Refresh(string userName ,RefreshDto refreshDto)
4{
5   return Ok(_authenticate.Refresh(userName, refreshDto));
6}

创建一个控制器,并书写一个Refresh的刷新方法,当我们前端发现Token失效的时候,我们将会携带失效的JWT以及之前登录时产生的RefreshToken来重新生成一个Token和RefreshToken ,以此来减轻对数据库查询压力。。。
那么这个Refresh方法的逻辑是什么呢?

1/// <summary>2/// 刷新验证 生成接口服务3/// </summary>4public interface IRefreshManager5{6        ResponseModel Refresh(RefreshDto refreshDto, Dictionary<string, string> dic, Claim[] claims);7}8/// <summary>9/// 刷新验证 生成接口实现
10/// </summary>
11public class RefreshManagerImpl:IRefreshManager
12    {
13        private readonly string _key;
14        private readonly IGenerateRefreshToken _generateRefreshToken;
15
16        public RefreshManagerImpl(string key, IGenerateRefreshToken generateRefreshToken)
17        {
18            this._key = key;
19            this._generateRefreshToken = generateRefreshToken;
20        }
21
22        public ResponseModel Refresh(RefreshDto refreshDto,Dictionary<string,string> dic,Claim[] claims)
23        {
24            var tokenHandler = new JwtSecurityTokenHandler();
25            SecurityToken validatedToken;
26            // 根据过期token获取一个 SecurityToken 
27            var principal =tokenHandler.ValidateToken(refreshDto.JwtToken, new TokenValidationParameters()
28            {
29                ValidateIssuerSigningKey = true,
30                IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(_key)),
31                ValidateIssuer = false,
32                ValidateAudience = false,
33                ValidateLifetime = false, // 不对tojen过期进行验证
34            }, out validatedToken);
35            var jwtToken = validatedToken as JwtSecurityToken;
36            // 算法验证
37            if (jwtToken == null || !jwtToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256,StringComparison.InvariantCultureIgnoreCase))
38            {
39                throw new SecurityTokenException("token 不合法");
40            }
41            // 判读refreshToken是否是此用户生成的
42            var userName = principal.Identity.Name;
43            if(refreshDto.RefreshToken!=dic[userName] && refreshDto.RefreshToken==null)
44            {
45                throw new SecurityTokenException("refreshToken 不合法");
46            }
47
48            // 生成新token
49            var jwtSecurityToken = new JwtSecurityToken(
50                claims: claims, // 需要一个Claims对象  需要根据用户信息自定义生成生成
51                expires: DateTime.UtcNow.AddSeconds(60),
52                signingCredentials: new SigningCredentials(
53                    new SymmetricSecurityKey(Encoding.ASCII.GetBytes(_key)),
54                    SecurityAlgorithms.HmacSha256Signature)
55                );
56
57            // 生成新token 和 refreshToken
58            var token = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
59            var refreshToken = _generateRefreshToken.GenerateRefreshTokenStr();
60            // 返回结果
61            return new ResponseModel() { JwtToken = token, RefreshToken = refreshToken };
62        }
63
64
65    }

上述就是Refresh方法的核心逻辑(详情见注释),我们将这个接口服务注入到容器中,以供控制器Api接口调用

1builder.Services.AddSingleton<IRefreshManager>(x => new RefreshManagerImpl(key, x.GetService<IGenerateRefreshToken>()));

调用此服务 由IAuthenticate.cs里面的方法调用

1public ResponseModel Refresh(string userName,RefreshDto refreshDto)
2        {
3            var claims = new Claim[] { new Claim(ClaimTypes.Name, userName) };
4            var tokenModel = _refreshManager.Refresh(refreshDto, RefreshTokens, claims);
5            RefreshTokens[userName] = tokenModel.RefreshToken;
6            return tokenModel;
7        }

以上便是JWT 生成RefreshToken的方法的大概逻辑,加上前面写的几篇文章,身份鉴权授权就暂分享这么多,后面再补充,最后感谢趣编程ACE公众号以及其他帮我分享文章的平台,Thanks~

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

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

相关文章

C#访问postgresql数据库类MyPostDB的实现

为了访问PostgreSQL数据库&#xff0c;需要从pgfoundry网站&#xff0c;下载Npgsql .Net Data Provider for Postgresql的组件。 访问 URL&#xff1a;http://pgfoundry.org/frs/?group_id1000140&#xff0c;请按照自己的VS及.NET版本下载相应的版本。下载后解压缩zip文件&am…

单链表Java实现

近期在复习基本数据结构&#xff0c;本文是单链表的Java实现&#xff0c;包含对单链表的实现插入删除查找遍历等。最后还实现了单链表的逆置。 实现了多项式相加&#xff0c;多项式相乘。原文章及完整源码在这里 http://binhua.info/datastructure/%E5%8D%95%E9%93%BE%E8%A1%A8…

solidity struct 结构体创建与使用浅学 (四)

环境说明&#xff1a; Ide&#xff1a;在线remix Solidity IDE 语言&#xff1a;solidity solidity 版本号&#xff1a;0.4.20 Tip&#xff1a;如果一点都不懂的建议从头开始看 运行结果截图我不赘述&#xff0c;所有合约代码均通过个人检测。请按照标准进行操作&#xff0c;如…

ORACLE TDE 透明数据加密技术

从ORALE 10GR2开始出现透明数据加密技术(Transparent Data Encryption&#xff0c;TDE)TDE用来对数据加密&#xff0c;通常 SQL 执行的应用程序逻辑不需要进行更改&#xff0c;仍能正常运行。 换言之&#xff0c;应用程序可以使用同一语法将数据插入到应用程序表中&#xff0c;…

linux之杀死某个应用或命令的一行终极命令

1 问题 我使用wget url然后失败了&#xff0c;然后老是去连接&#xff0c;我想停下来&#xff0c;ctrlc也没用&#xff0c;只能通过强杀死进程来实现。 2 解决办法 ps -A | grep wget | cut -c 1-6 | xargs kill -9 3总结 以后杀进行杀应用都用下面这个命令一行搞定 ps -A …

C语言实现万年历记事本,简单实用的layui日历标注记事本代码

一款简单实用的layui日历标注记事本代码&#xff0c;响应式自适应电脑、平板跟手机移动端&#xff0c;可以在日历上设置每日事项标注记录&#xff0c;支持撤销、添加、修改标注记录。查看演示下载资源&#xff1a;52次 下载资源下载积分&#xff1a;20积分js代码 layui.use([la…

jq checked 设置问题

前两天写一页面 需做一单选按钮。设置如下 $(".design p").bind("click",function() { $(".design p").removeClass("checked");      $(this).addClass("checked").children("input"…

围棋经典棋谱_秀秀老师:茶艺师也要学好围棋

“引清风&#xff0c;邀明月&#xff0c;去来兮。省多少闲是闲非。临山近水&#xff0c;近些松竹向些梅。书院茶香几多般&#xff0c;诗酒琴棋。无萦无烦恼&#xff0c;无别离。于中国文人雅士而言&#xff0c;茶与棋&#xff0c;皆是清雅之物事。曹臣《舌花录》中&#xff0c;…

基于 Dapr 和 .NET 开发云原生应用(奉上视频+资料)

点击蓝字/关注我序言&#xff1a;今年是.NET20周年&#xff0c;为了传播.NET和营造.NET技术氛围举办了此次云原生开发挑战赛&#xff0c;请来众多业界大咖来给大家分享技术&#xff0c;为大家参赛做预热&#xff0c;参赛的朋友都可获得51Aspx 500积分和微软亲签证书&#xff0c…

linux之strace命令跟踪进程的系统调用

1 系统调用 操作系统的进程空间分为用户空间和内核空间,操作系统内核直接运行在硬件上,提供设备管理、内存管理、任务调度等功能,我们用户空间不能直接调用,所以就有了系统调用(运行在用户空间的程序向操作系统内核请求需要更高权限运行的服务),系统调用提供用户程序与…

solidity bytes 智能合约开发知识浅学(五点一)bytes基本概念

环境说明&#xff1a; Ide&#xff1a;在线remix Solidity IDE 语言&#xff1a;solidity solidity 版本号&#xff1a;0.4.20 Tip&#xff1a;如果一点都不懂的建议从头开始看 运行结果截图我不赘述&#xff0c;所有合约代码均通过个人检测。请按照标准进行操作&#xff0c;如…

C#连接Excel和Access(包括2003和2007版)方法总结

一、说明: C#采用OLEDBConnection连接Excel、Access。要连接的数据源版本不同,连接字符串也不同。 97-2003版本 EXCEL Provider=Microsoft.Jet.OLEDB.4.0;Data Source=文件位置;Extended Properties=Excel 8.0;HDR=Yes;IMEX=1

Android启动过程五个步骤,Android启动流程、app启动原理

从头分析整理学习底层知识。Android 众多基于Linux内核的系统类似, 启动系统时, bootloader启动内核和init进程. init进程分裂出更多名为"daemons(守护进程)"的底层的Linux进程, 诸如android debug deamon, USB deamon等. 这些守护进程处理底层硬件相关的接口.随后, …

【Spring-AOP-学习笔记-3】@Before前向增强处理简单示例

项目结构程序代码HelloImpl.javaWorldImpl.java定义切面类package org.crazyit.app.aspect;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;// 定义一个切面Aspectpublic class AuthAspect{ // 匹配org.crazyit.app.service.impl包下所…

排序算法分析

我们都知道&#xff0c;在应届面试的时候&#xff0c;问到最多的就是快速排序&#xff0c;快速排序是最经典、最常用的排序算法&#xff0c;因为它的平均效率最优&#xff0c;也最稳定。 快速排序使用了分治的算法思想&#xff0c;分治算法本身理解起来很符合人类的思路&#x…

sklearn 线性回归_使用sklearn库做线性回归拟合

背景资料随着海拔高度的上升&#xff0c;温度越来越低&#xff0c;经过气象专家的研究&#xff0c;在一定的海拔高度范围内&#xff0c;高度和温度呈线性关系。现有一组实测资料&#xff0c;我们需要对这些数据进行处理拟合&#xff0c;获得此线性关系。解决思路采用sklearn库中…

VS2022之DebuggerVisualizer

在Debug程序时&#xff0c;面对一些大集合&#xff0c;之前是这样查看的&#xff0c;如下图&#xff0c;这样看起来不直观&#xff0c;集合中的数据只能一个一个实体查看&#xff1a;VS2022预览版带来一个新功能&#xff0c;集合表格可视化&#xff0c;比如下面这样一段代码&am…

Web程序员的Mysql进阶序一之sql使用分类及基础

一般sql语句分为3类&#xff1a;DDL、DML和DCL。 DDL&#xff1a;数据库定义类操作&#xff0c;例如&#xff1a;create、drop、alter DML&#xff1a;数据库数据操作&#xff0c;例如&#xff1a;insert、delete、update、select DCL&#xff1a;数据库权限安全操作&#xff0…

NPOI 将DataGridView导出到Excel

导出为xls格式用HSSF&#xff0c;xlsx用XSSF。 1、类 using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; using System.Text; using NPOI.HSSF.UserModel; using System.IO; using NPOI.SS.UserModel;public class ExportExce…

android log.d 格式化,android – 在我的代码中使用Log.d()或Log.e()

考虑使用它&#xff1a;isLoggable()Checks to see whether or not a log for the specified tag is loggable at the specified level. The default level of any tag is set to INFO. This means that any level above and including INFO will be logged. Before you make a…