最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue中雙token和無感刷新token的區(qū)別

 更新時間:2024年05月12日 08:36:07   作者:鋒行天下  
本文主要介紹了vue中雙token和無感刷新token的區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

為什么有這篇小作文?

最近要給自己的項目加上token自動續(xù)期,但是在網(wǎng)上搜的寫法五花八門,有的光前端部分就寫了幾百行代碼,我看著費勁,摸了半天也沒有實現(xiàn),所以決定自己造輪子

項目構(gòu)成

  • 后端部分:使用golang的gin框架起的服務(wù)
  • 前端部分:vue+elementui

先說后端部分,后端邏輯相對前端簡單點,關(guān)鍵三步

登陸接口生成雙token

"github.com/dgrijalva/jwt-go"
func (this UserController) DoLogin(ctx *gin.Context) {
    username := ctx.Request.FormValue("username")
    passWord := ctx.Request.FormValue("password")
    passMd5 := middlewares.CreateMD5(passWord)
    expireTime := time.Now().Add(10 * time.Second).Unix() //token過期時間10秒,主要是測試方便
    refreshTime := time.Now().Add(20 * time.Second).Unix() //刷新的時間限制,超過20秒重新登錄
    user := []modules.User{}
    err := modules.DB.Model(&modules.User{}).Where("username = ? AND password = ?", username, passMd5).Find(&user).Error
    if err != nil || len(user) == 0 {
        ctx.JSON(400, gin.H{
            "success": false,
            "message": "用戶名或密碼錯誤",
        })
    } else {
        println("expireTime", string(rune(expireTime)))
        myClaims := MyClaims{
            user.Id,
            jwt.StandardClaims{
                ExpiresAt: expireTime,
            },
        }
        myClaimsRefrrsh := MyClaims{
            user.Id,
            jwt.StandardClaims{
                ExpiresAt: refreshTime,
            },
        }
        jwtKey := []byte("lyf123456")
        tokenObj := jwt.NewWithClaims(jwt.SigningMethodHS256, myClaims)
        tokenStr, err := tokenObj.SignedString(jwtKey)
        tokenFresh := jwt.NewWithClaims(jwt.SigningMethodHS256, myClaimsRefrrsh)
        tokenStrRefresh, err2 := tokenFresh.SignedString(jwtKey)
        if err != nil && err2 != nil {
            ctx.JSON(200, gin.H{
                "message": "生成token失敗",
                "success": false,
            })
        } else {
            ctx.JSON(200, gin.H{
                "message":      "登錄成功",
                "success":      true,
                "token":        tokenStr,//數(shù)據(jù)請求的token
                "refreshToken": tokenStrRefresh,//刷新token用的
            })
        }
    }
}

刷新token的方法

func (this UserController) RefrshToken(ctx *gin.Context) {
    tokenData := ctx.Request.Header.Get("Authorization") //這里是個關(guān)鍵點,刷新token時也要帶上token,不過這里是前端傳的refreshToken
    if tokenData == "" {
        ctx.JSON(401, gin.H{
            "message": "token為空",
            "success": false,
        })
        ctx.Abort()
        return
    }
    tokenStr := strings.Split(tokenData, " ")[1]
    _, claims, err := middlewares.ParseToken(tokenStr)
    expireTime := time.Now().Add(10 * time.Second).Unix()
    refreshTime := time.Now().Add(20 * time.Second).Unix()
    if err != nil {
        ctx.JSON(400, gin.H{
            "success": false,
            "message": "token傳入錯誤",
        })
    } else {
        myClaims := MyClaims{
            claims.Uid,
            jwt.StandardClaims{
                ExpiresAt: expireTime,
            },
        }
        myClaimsRefrrsh := MyClaims{
            claims.Uid,
            jwt.StandardClaims{
                ExpiresAt: refreshTime,
            },
        }
        jwtKey := []byte("lyf123456")
        tokenObj := jwt.NewWithClaims(jwt.SigningMethodHS256, myClaims)
        tokenStr, err := tokenObj.SignedString(jwtKey)
        tokenFresh := jwt.NewWithClaims(jwt.SigningMethodHS256, myClaimsRefrrsh)
        tokenStrRefresh, err2 := tokenFresh.SignedString(jwtKey)
        if err != nil && err2 != nil {
            ctx.JSON(400, gin.H{
                "message": "生成token失敗",
                "success": false,
            })
        } else {
            ctx.JSON(200, gin.H{
                "message":      "刷新token成功",
                "success":      true,
                "token":        tokenStr,
                "refreshToken": tokenStrRefresh,
            })
        }
    }
}

路由中間件里驗證token

package middlewares

import (
    "strings"

    "github.com/dgrijalva/jwt-go"
    "github.com/gin-gonic/gin"
)

type MyClaims struct {
    Uid int
    jwt.StandardClaims
}

func AuthMiddleWare(c *gin.Context) {
    tokenData := c.Request.Header.Get("Authorization")
    if tokenData == "" {
        c.JSON(401, gin.H{
            "message": "token為空",
            "success": false,
        })
        c.Abort()
        return
    }
    tokenStr := strings.Split(tokenData, " ")[1]
    token, _, err := ParseToken(tokenStr)
    if err != nil || !token.Valid {
         // 這里我感覺覺是個關(guān)鍵點,我看別人寫的,過期了返回401,但是前端的axios的響應(yīng)攔截器里捕獲不到,所以我用201狀態(tài)碼,
        c.JSON(201, gin.H{
            "message": "token已過期",
            "success": false,
        })
        c.Abort()
        return
    } else {
        c.Next()
    }
}

func ParseToken(tokenStr string) (*jwt.Token, *MyClaims, error) {
    jwtKey := []byte("lyf123456")
    // 解析token
    myClaims := &MyClaims{}
    token, err := jwt.ParseWithClaims(tokenStr, myClaims, func(token *jwt.Token) (interface{}, error) {
        return jwtKey, nil
    })
    return token, myClaims, err
}

總結(jié)一下:后端部分三步,1.登陸時生成雙token,2,路由中間件里驗證token,過期時返回201狀態(tài)碼(201是我私人定的,并不是行業(yè)標準)。3,刷新token的方法里也和登陸接口一樣返回雙token

前端部分

前端部分在axios封裝時候加攔截器判斷token是否過期,我這里跟別人寫的最大的不同點是:我創(chuàng)建了兩個axios對象,一個正常數(shù)據(jù)請求用(server),另一個專門刷新token用(serverRefreshToken),這樣寫的好處是省去了易錯的判斷邏輯

import axios from 'axios'
import { ElMessage } from 'element-plus'
import router from '../router'
//數(shù)據(jù)請求用
const server=axios.create({
  baseURL:'/shopApi',
  timeout:5000
})
// 刷新token專用
const serverRefreshToken=axios.create({
  baseURL:'/shopApi',
  timeout:5000
})
//獲取新token的方法
async function getNewToken(){
  let res=await serverRefreshToken.request({
    url:`/admin/refresh`,
    method:"post",
  })
  if(res.status==200){
    sessionStorage.setItem("token",res.data.token)
    sessionStorage.setItem("refreshToken",res.data.refreshToken)
    return true
  }else{
    ElMessage.error(res.data.message)
    router.push('/login')
    return false
  }
}
//這里是正常獲取數(shù)據(jù)用的請求攔截器,主要作用是給所有請求的請求頭里加上token
server.interceptors.request.use(config=>{
  let token=""
  token=sessionStorage.getItem("token")
  if(token){
    config.headers.Authorization="Bearer "+token
  }
  return config
},error=>{
  Promise.reject(error)
})
//這里是正常獲取數(shù)據(jù)用的響應(yīng)攔截器,正常數(shù)據(jù)請求都是200狀態(tài)碼,當攔截到201狀態(tài)碼時,代表token過期了,
// 應(yīng)熱心小伙伴的提醒,加上防止token過期后正好短時間內(nèi)多個請求重復(fù)刷新token,刷新token成功再請求
let isRefreshing=false
let refreshFnArr=[]
server.interceptors.response.use(async(res)=>{
  if(res.status==201){
    if(!isRefreshing){
    // 如果正好段時間內(nèi)觸發(fā)了多個請求
      isRefreshing=true
      let bl=await getNewToken()
      if(bl){
        refreshFnArr.forEach(fn=>{
          fn()
        })
        refreshFnArr=[]
        res= await server.request(res.config)
        isRefreshing=false
      }
    }else{
      return new Promise(resolve=>{
        refreshFnArr.push(
          ()=>{
            resolve(res.config)
          }
        )
      })
    }
  }
  return res
},error=>{
  if(error.response.status==500||error.response.status==401||error.response.status==400){
    router.push('/login')
    ElMessage.error(error.response.data.message)
    Promise.reject(error)
  }
  
})
//這里是刷新token專用的axios對象,他的作用是給請求加上刷新token專用的refreshToken
serverRefreshToken.interceptors.request.use(config=>{
  let token=""
  token=sessionStorage.getItem("refreshToken")
  if(token){
    config.headers.Authorization="Bearer "+token
  }
  return config
},error=>{
  Promise.reject(error)
})
export default server

總結(jié)一下,前端部分:1,正常數(shù)據(jù)請求和刷新token用的請求分開了,各司其職。省去復(fù)雜的判斷。2,獲取新的token和refreshToken后更新原來舊的token和refreshToken。(完結(jié))

到此這篇關(guān)于vue中雙token和無感刷新token的區(qū)別的文章就介紹到這了,更多相關(guān)vue中雙token和無感刷新token內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 微信小程序scroll-view實現(xiàn)字幕滾動

    微信小程序scroll-view實現(xiàn)字幕滾動

    這篇文章主要為大家詳細介紹了微信小程序scroll-view實現(xiàn)字幕滾動效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • document.write的幾點使用心得

    document.write的幾點使用心得

    一直用document.write()方法向瀏覽器中顯示數(shù)據(jù)用,把它當做Alert()使用, 看來這樣用有些大材小用了,下面說說它的主要用處。
    2014-05-05
  • javascript 獲取元素樣式必殺技

    javascript 獲取元素樣式必殺技

    這篇文章主要介紹了javascript 獲取元素樣式必殺技,需要的朋友可以參考下
    2014-05-05
  • JS?for?in遍歷對象順序不對解決辦法

    JS?for?in遍歷對象順序不對解決辦法

    最近使用for-in語句遍歷對象屬性時發(fā)現(xiàn)遍歷順序并非屬性構(gòu)建順序,這篇文章主要給大家介紹了關(guān)于JS?for?in遍歷對象順序不對的解決辦法,需要的朋友可以參考下
    2023-11-11
  • Js判斷CSS文件加載完畢的具體實現(xiàn)

    Js判斷CSS文件加載完畢的具體實現(xiàn)

    在多數(shù)情況下我們不需要判斷css文件是否加載成功了,但有些時間這個功能還是需要的,今天我來整理了兼容各種瀏覽器的判斷CSS文件加載完畢實現(xiàn)方法與各位分享
    2014-01-01
  • JavaScript實現(xiàn)節(jié)假日日歷應(yīng)用開發(fā)全過程

    JavaScript實現(xiàn)節(jié)假日日歷應(yīng)用開發(fā)全過程

    在Web開發(fā)中,日歷控件是一個常見的組件,用于顯示日期并幫助用戶選擇日期,這篇文章主要介紹了JavaScript實現(xiàn)節(jié)假日日歷應(yīng)用開發(fā)的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-10-10
  • javascript 簡單抽屜效果的實現(xiàn)代碼

    javascript 簡單抽屜效果的實現(xiàn)代碼

    javascript 簡單抽屜效果的實現(xiàn)代碼,需要的朋友可以參考下,大家自行測試。
    2010-03-03
  • JS實現(xiàn)圖片橫向滾動效果示例代碼

    JS實現(xiàn)圖片橫向滾動效果示例代碼

    圖片橫向滾動效果,大家可能都已經(jīng)很熟悉了,本文為大家介紹下使用js實現(xiàn)橫向滾動效果,喜歡的朋友可以參考下,希望對大家有所幫助
    2013-09-09
  • jszip插件實現(xiàn)圖片打包下載的方法分析

    jszip插件實現(xiàn)圖片打包下載的方法分析

    這篇文章主要介紹了jszip插件實現(xiàn)圖片打包下載的方法,結(jié)合實例形式分析了JavaScript使用jszip插件依據(jù)圖片列表打包下載zip壓縮文件的相關(guān)操作技巧,需要的朋友可以參考下
    2023-05-05
  • 學(xué)做Bootstrap的第一個頁面

    學(xué)做Bootstrap的第一個頁面

    這篇文章主要為大家介紹了學(xué)做Bootstrap的第一個頁面,這是學(xué)bootstrap的第一個頁面,還有許多需要改進的地方,希望大家批評指正
    2016-05-05

最新評論

蓝田县| 凤翔县| 阿拉善右旗| 册亨县| 阿尔山市| 六安市| 奉贤区| 贺州市| 久治县| 广宁县| 鹤庆县| 贡嘎县| 汪清县| 澄城县| 儋州市| 南投县| 长治县| 始兴县| 东安县| 卓资县| 惠东县| 大城县| 中江县| 阳泉市| 信阳市| 桦川县| 湖北省| 岑巩县| 大厂| 龙陵县| 衡山县| 庄河市| 喜德县| 呈贡县| 绥芬河市| 平凉市| 陇西县| 娄烦县| 错那县| 荔浦县| 亳州市|