弯道超车-Token处理
弯道超车-Token处理
一、 RefreshToken滑动过期处理:是在使用JWT进行授权的时候AccessToken过期了,然后通过如上token去重新获取可用的token,简单点就是说当用户在持续使用token的时候,我们需要做到每次在基础上加对应的时间,而不是直接跳转到登录首页。接下来就是介绍如何进行滑动过期的操作。先看如下图:
1.
二、后端代码处理:
1. 生成Token+RefreshToken,重点是第一步的时候,生成refreshToken的时候,需要把用户的信息缓存起来,方便下次使用该token来兑换。
/// <summary> /// 生成Token+RefreshToken /// </summary> /// <param name="name"></param> /// <param name="password"></param> /// <returns></returns> [Route("LoginWithRefresh")] [HttpPost] public string LoginWithRefresh([FromForm] string name, [FromForm] string password) { Console.WriteLine($"This is LoginWithRefresh name={name} password={password}"); if ("Eleven".Equals(name, StringComparison.OrdinalIgnoreCase) && "123456".Equals(password))//应该数据库 { CurrentUserModel currentUser = new CurrentUserModel() { Id = 123, Account = "132313", EMail = "test@qq.com", Mobile = "123456", Sex = 1, Age = 33, Name = "wj", Role = "Admin" }; var tokenPair = this._iJWTService.GetTokenWithRefresh(currentUser); if (tokenPair != null && !string.IsNullOrEmpty(tokenPair.Item1)) { return JsonConvert.SerializeObject(new AjaxResult<string>() { Result = true, Message = "验证成功", TValue = tokenPair.Item1, OtherValue = tokenPair.Item2//写在OtherValue }); } else { return JsonConvert.SerializeObject(new AjaxResult<string>() { Result = false, Message = "颁发token失败", TValue = "" }); } } else { return JsonConvert.SerializeObject(new AjaxResult<string>() { Result = false, Message = "验证失败", TValue = "" }); } }
2. 同时提供一个刷新token的方法: 通过refreshToken去换有效的token
[Route("RefreshToken")] [HttpPost] public async Task<string> RefreshToken([FromForm] string refreshToken) { await Task.CompletedTask; if (!refreshToken.ValidateRefreshToken()) { return JsonConvert.SerializeObject(new AjaxResult<string>() { Result = false, Message = "refreshToken过期了", TValue = "" }); } var token = this._iJWTService.GetTokenByRefresh(refreshToken); if (!string.IsNullOrEmpty(token)) { return JsonConvert.SerializeObject(new AjaxResult<string>() { Result = true, Message = "刷新Token成功", TValue = token, OtherValue = refreshToken//写在OtherValue }); } else { return JsonConvert.SerializeObject(new AjaxResult<string>() { Result = false, Message = "刷新token失败", TValue = "" }); } }
三、前端处理
1. 前端主要是在调用的时候使用token去获取,然后发现token过期了,就调用获取refreshToken的方法,成功以后就继续执行之前的操作,反之就跳转登录页。
相关代码示例:
@section Scripts{ <script type="text/javascript"> $(function () { $("#btnLogin").on("click", function () { $.ajax({ url: "/Token/Login?Name=Eleven&Password=123456", type: "get", data: {}, success: function (data) { if(data.result){ localStorage["token"] =data.tValue; alert(data.tValue); } }, datatype: "json" }); }); $("#btnGet").on("click", function () { $.ajax({ url: "/Token/InfoGet", type: "get", data: {}, beforeSend: function (XHR) { //发送ajax请求之前向http的head里面加入验证信息 XHR.setRequestHeader('Authorization', 'Bearer ' + localStorage["token"]); }, success: function (data) { alert(data.result); alert(data.tValue); } , datatype: "json" }) }); $("#btnPost").on("click", function () { $.ajax({ url: "/Token/InfoPost", type: "post", data: {}, beforeSend: function (XHR) { //发送ajax请求之前向http的head里面加入验证信息 XHR.setRequestHeader('Authorization', 'Bearer ' + localStorage["token"]); }, success: function (data) { alert(data.result); alert(data.tValue); } , datatype: "json" }); }); //Refresh $("#btnLoginRefresh").on("click", function () { $.ajax({ url: "/Token/LoginWithRefresh?Name=Eleven&Password=123456", type: "get", data: {}, success: function (data) { if(data.result){ localStorage["accessToken"] =data.tValue; //alert(data.tValue); localStorage["refreshToken"] = data.otherValue; //alert(data.otherValue); } }, datatype: "json" }); }); $("#btnGetRefresh").on("click", function () { $.ajax({ url: "/Token/InfoGet", type: "get", data: {}, beforeSend: function (XHR) { //发送ajax请求之前向http的head里面加入验证信息 XHR.setRequestHeader('Authorization', 'Bearer ' + localStorage["accessToken"]); }, success: function (data) { alert(data.result+data.tValue); }, datatype: "json", error:function(xhr, status, error){ alert(xhr.getAllResponseHeaders());//打印全部头信息 alert(xhr.status);//也可以用状态作比较 if(xhr.getAllResponseHeaders().indexOf('jwtchallenge: expired')>0) { //refreshToken($("#btnGetRefresh").click);//直接传递回调最好,没成功 refreshToken($("#btnGetRefresh"));//传递按钮 } } }); }); var refreshTime=0; function refreshToken(callback){ alert("refresh-token"); if(refreshTime==0) { refreshTime++; } else { alert("需要重新登陆"); //跳转登录页 } $.ajax({ url: "/Token/LoginByRefresh", type: "post", data: {"refreshToken":localStorage["refreshToken"]}, success: function (data) { if(data.result){ localStorage["accessToken"] =data.tValue; localStorage["refreshToken"] =data.otherValue; //alert(data.tValue); //callback(); callback.trigger("click"); } }, datatype: "json" }); } $("#btnPostRefresh").on("click", function () { $.ajax({ url: "/Token/InfoPost", type: "post", data: {}, beforeSend: function (XHR) { //发送ajax请求之前向http的head里面加入验证信息 XHR.setRequestHeader('Authorization', 'Bearer ' + localStorage["accessToken"]); }, success: function (data) { alert(data.result); alert(data.tValue); } , datatype: "json", error:function(xhr, status, error){ //alert(xhr.getAllResponseHeaders());//打印全部头信息 //alert(xhr.status);//也可以用状态作比较 if( xhr.getAllResponseHeaders().indexOf('jwtchallenge: expired')>0) { //refreshToken($("#btnGetRefresh").click);//直接传递回调最好,没成功 refreshToken($("#btnGetRefresh"));//传递按钮 } } }) }); }); </script> }
2. 解答:如何实现调用之前的接口的?
关键代码:
callback.trigger("click");
四、在vue项目中如何进行执行之前接口的操作?
参考代码如下:
axios.interceptors.response.use(success, async (error) => { let {status} = error.response; if (status == 401) { let res = await getrefreshToken(refreshToken); window.localstorage.token = res.token; return axios.request(error.config); } return Promise.reject() })
参考文章:https://www.jianshu.com/p/f2ca652a5d29
以上就是token相关的整理,谢谢学习,点赞,关注,共同进步!!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
2020-09-30 网站优化之缓存--页面缓存