弯道超车-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相关的整理,谢谢学习,点赞,关注,共同进步!!!

 

原文地址:https://www.cnblogs.com/wangjinya/p/15358383.html