JWT实现跨域请求
JWT實現跨域請求
文章目錄
- JWT實現跨域請求
- cookie的弊端
- 使用JWT實現跨域
- 案例
 
cookie的弊端
最近在做一個web項目,我想實現一個功能:客戶端瀏覽器每次訪問首頁的時候,就從請求中獲取cookie,如果cookie中含有用戶信息,就自動為用戶登錄,否則就不登陸。
 但是我的前端是基于vue實現的,起在8080端口,服務端起在9090端口,眾所周知cookie是不可以跨域的,滿足不同協議,不同域名,不同端口即為跨域,雖然前后端都部署在localhost,但是不同端口造成了跨域。
雖然我們可以采取cors策略等辦法實現跨域,但是相對來說增添了麻煩。
使用JWT實現跨域
我采取了網上的很多辦法,依然不能讓cookie實現跨域,于是就想到了使用JWT+localStorage的辦法。其實JWT是可以放在cookie里面的,但是在本文的場景中cookie不能跨域。
大致思路是這樣的:
案例
在這里我做了一個簡單的小demo來演示大致的流程,用了gin、vue以及一個go的jwt庫:Gin中使用JWT。
客戶端
首先在前端創建一個storage.js文件來對localStorage做一次封裝:
<template><div class="form"><input type="text" v-model="phoneNumber"><input type="submit" value="提交" @click="submit"><br><br><input type="submit" value="第二次提交" @click="submit2"></div> </template><script> import storage from '../../assets/storage' export default {data() {return {phoneNumber: null,}},methods: {submit() {var forms = new FormData();forms.append("phoneNumber", this.phoneNumber);this.$axios.post("http://127.0.0.1:9092/token", forms).then((res) => {storage.set("access_token", res.data.token)console.log("后端發送來的token儲存到本地:");console.log(res.data.token);})},submit2() {var forms = new FormData();forms.append("Authorization", 'Bearer ' + storage.get("access_token"))console.log("從瀏覽器緩存取出token發送:" + forms.get("Authorization"));this.$axios.post("http://127.0.0.1:9092/token2", forms).then((res) => {console.log("打印后端的數據:");console.log(res.data.message);})},} } </script>
 服務端
首先創建一個jwt的model在token.go文件中,我們在里面定義了jwt結構體、生成token令牌的方法以及解析token令牌的方法:
package modelsimport ("errors""github.com/dgrijalva/jwt-go""time" )// MyClaims 自定義結構體 type MyClaims struct {PhoneNumber string `json:"phoneNumber"`jwt.StandardClaims }const TokenExpireDuration = time.Hour * 720 // 自定義密鑰 var mySecret = []byte("123456")// GenToken 生成jwt func GenToken(phoneNumber string) (string, error) {c := MyClaims{phoneNumber,jwt.StandardClaims {ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(), // 過期時間Issuer: "goShop", // 簽發人},}// 使用HS256加密方式token := jwt.NewWithClaims(jwt.SigningMethodHS256, c)tmp, err := token.SignedString(mySecret)return tmp, err }// ParseToken 解析token func ParseToken(tokenString string) (*MyClaims, error) {token, err := jwt.ParseWithClaims(tokenString, &MyClaims{}, func(token *jwt.Token) (interface{}, error) {return mySecret, nil})if err != nil {return nil, err}if Claims, ok := token.Claims.(*MyClaims); ok && token.Valid {return Claims, nil}return nil, errors.New("invalid token") }最后我們在入口函數中定義接受客戶端兩次請求的路由:
package testsimport ("fmt""github.com/gin-gonic/gin""go-shop/middleware""go-shop/models""net/http""testing" )func authHandler(c *gin.Context) {phoneNumber := c.PostForm("phoneNumber")// 生成tokentokenString, _ := models.GenToken(phoneNumber)fmt.Println("生成token:", tokenString)c.JSON(http.StatusOK, gin.H{"msg" : "success","token" : tokenString,}) } func authHandler2(c *gin.Context) {fmt.Println("token認證成功!")c.JSON(http.StatusOK, gin.H{"message" : "success",}) }func TestJWT(t *testing.T) {r := gin.Default()r.Use(middleware.Cors())r.POST("/token", authHandler)r.POST("/token2", middleware.JWTAuthMiddleware(),authHandler2)r.Run(":9092") }在表單中輸入我的手機號碼,然后點擊提交,服務端會生成一段token令牌發送回來:
 然后點擊第二次提交按鈕,客戶端會把令牌從localStorage中提取出來,加在request中發送給服務端,服務端驗證成功以后,發送反饋消息:
參考資料:
vue-localStorage 緩存過期時間
vue保存后端發來的token+vue向后端發送網絡請求攜帶token
總結
 
                            
                        - 上一篇: 01easyui
- 下一篇: DFS应用:纵火犯题解
