<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          技能學(xué)習(xí):學(xué)習(xí)使用golang(gin框架) + vue.js,開發(fā)前端全棧網(wǎng)站-9.登...

          共 4527字,需瀏覽 10分鐘

           ·

          2021-08-25 14:39

          技能學(xué)習(xí):學(xué)習(xí)使用golang(gin框架) + vue.js,開發(fā)前端全棧網(wǎng)站-9.登錄功能(三):登錄的token驗(yàn)證

          相關(guān)文章:
          技能學(xué)習(xí):學(xué)習(xí)使用golang(gin框架) + vue.js,開發(fā)前端全棧網(wǎng)站-1.工具和本地環(huán)境

          技能學(xué)習(xí):學(xué)習(xí)使用golang(gin框架) + vue.js,開發(fā)前端全棧網(wǎng)站-8.模型的關(guān)聯(lián)——無(wú)限層級(jí)分類
          技能學(xué)習(xí):學(xué)習(xí)使用golang(gin框架) + vue.js,開發(fā)前端全棧網(wǎng)站-9.登錄功能(一):管理員功能的實(shí)現(xiàn)
          技能學(xué)習(xí):學(xué)習(xí)使用golang(gin框架) + vue.js,開發(fā)前端全棧網(wǎng)站-9.登錄功能(二):用戶登錄和密碼驗(yàn)證
          技能學(xué)習(xí):學(xué)習(xí)使用golang(gin框架) + vue.js,開發(fā)前端全棧網(wǎng)站-9.登錄功能(三):登錄的token驗(yàn)證
          技能學(xué)習(xí):學(xué)習(xí)使用golang(gin框架) + vue.js,開發(fā)前端全棧網(wǎng)站-10.生產(chǎn)環(huán)境編譯

          1.生成token

          go語(yǔ)言中生成token的方法被封裝在了jwt中,gin框架使用jwt又進(jìn)行了進(jìn)一步封裝,在"github.com/dgrijalva/jwt-go"里。
          (1)安裝jwt包:jwt-go

          go get github.com/dgrijalva/jwt-go

          3d9cae102317a928e3049bf12d3eb15c.webp
          (2)編寫生成token方法

          // 定義一個(gè)全局token密鑰,token密鑰隨意定義一串字符串
          var jwtkey = []byte("lskjdghfhkagflkagh")
          // 定義字符串格式token,方便之后token的轉(zhuǎn)化
          var tokenString string

          // 定義一個(gè)token模型,用于存放token信息,識(shí)別不同賬號(hào)
          type claims struct {
          UserId string
          jwt.StandardClaims
          }

          // 生成token
          // 傳入字符串格式用戶id,輸出字符串格式的token和錯(cuò)誤值
          func setToken(id string) (tokenString string, err error) {
          //
          // 定義token過期時(shí)間,一天后過期
          expireTime := time.Now().Add(1 * 24 * time.Hour)
          claims := &claims{
          UserId: id,
          StandardClaims: jwt.StandardClaims{
          ExpiresAt: expireTime.Unix(), // 過期時(shí)間,用上方定義的過期時(shí)間
          IssuedAt: time.Now().Unix(), // 生效時(shí)間,生成token的這一刻起
          Issuer: "127.0.0.1", // 生成者,本域名
          Subject: "user token", // 生成主題
          },
          }
          // 生成token
          token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
          // 根據(jù)之前定義的密鑰,將token轉(zhuǎn)化為加密字符串
          tokenString, err = token.SignedString(jwtkey)
          // 輸出
          return
          }

          5fefa95f37c7ab54135a1578dc4af0af.webp
          (2)編輯登錄接口方法,在其中使用token方法獲取token值
          75b1d24c54f4f7e9dbc30c42572dccca.webp
          編譯啟動(dòng),測(cè)試:
          b3a6a8f7ff5a731beaa743f2b5ea4e77.webp
          成功獲取token值。
          (3)最后將token值保存到前端本地儲(chǔ)存空間中,用于驗(yàn)證登錄狀態(tài):
          Login.vue:

          async login() {
          const res = await this.$http.post('login', this.model)
          console.log(res)

          // 存儲(chǔ)token值
          // sessionStorage是頁(yè)面緩存存儲(chǔ),關(guān)閉頁(yè)面后token值被清除,每次進(jìn)入頁(yè)面都需要進(jìn)行賬號(hào)登陸
          // localStorage是本地存儲(chǔ),關(guān)閉頁(yè)面后token值不會(huì)被清除,只要不清理瀏覽器緩存就無(wú)需再次進(jìn)行登錄操作
          localStorage.token = res.data.token

          // 登錄成功跳轉(zhuǎn)到網(wǎng)站首頁(yè)
          this.$router.push('/')
          // 使用vue效果在頁(yè)面展示結(jié)果
          this.$message({
          type: 'success',
          message: '登陸成功'
          })
          }

          b64be2620214ca2bf0a18b0624118685.webp
          保存測(cè)試,跳轉(zhuǎn)成功:
          42222fed8b1578b7e2792323987c377f.webp
          查找頁(yè)面存儲(chǔ)的token,可查詢到:
          a5e3940a1f2aea7fd2f939758fb8ffbc.webp

          2.驗(yàn)證token

          我們需要將token值存入發(fā)送請(qǐng)求的請(qǐng)求頭中,做到只要調(diào)用接口,就可以將token一并發(fā)送到后端,從而對(duì)token登陸狀態(tài)進(jìn)行比對(duì)驗(yàn)證。
          (1)前端admin端通過請(qǐng)求頭將token傳值給后端
          在http.js中全局設(shè)置獲取token,將token值傳入請(qǐng)求頭Request
          Headers中,然后后臺(tái)接口中直接從請(qǐng)求頭中獲取token,從而實(shí)現(xiàn)驗(yàn)證。
          這里使用axios里的Interceptors方法,詳細(xì)可查閱axios手冊(cè):
          bff1a25627075a156671d49cbb07ec7b.webp
          admin/http.js前端admin端將token傳入請(qǐng)求頭Request Header:

          // 使用axios的interceptors攔截器,將http調(diào)用時(shí)攔截
          http.interceptors.request.use(function(config){
          // 將token值傳入請(qǐng)求頭,"bearer + 空格"是代碼規(guī)范,看到Bearer(持票人)大家就明白是對(duì)token的驗(yàn)證
          config.headers.Authorization = 'bearer ' + localStorage.token
          return config
          }, function(error){
          // 錯(cuò)誤處理
          return Promise.reject(error)
          })

          a738136a862ab1a8f86c80186dfbd505.webp
          此時(shí)調(diào)用接口就可以將本地token傳給請(qǐng)求頭,測(cè)試:
          fe2216ea8a7a347bf3b80b11a3a773b5.webp
          (2)后端獲取請(qǐng)求頭中的token值,并解析token

          // 解析token
          func getToken() gin.HandlerFunc {
          return func(ctx *gin.Context) {
          // 從請(qǐng)求頭獲取token值
          tokenString := ctx.GetHeader("Authorization")

          // 判斷如果沒有token
          if tokenString == "" {
          ctx.JSON(http.StatusUnauthorized, gin.H{"code": 401, "msg": "您未登錄"})
          // 中間件中使用next()就執(zhí)行下一步,如果執(zhí)行abort()就不會(huì)執(zhí)行下一步
          ctx.Abort()
          // return
          }

          // 去除authorization中的"bearer"
          tokenString = strings.Trim(tokenString, "bearer")
          // 去除authorization中的空格
          tokenString = strings.Replace(tokenString, " ", "", -1)
          fmt.Println(tokenString)

          // 判斷token是否失效
          token, claims, err := ParseToken(tokenString)
          if err != nil || !token.Valid{
          ctx.JSON(http.StatusUnauthorized, gin.H{"code": 401, "msg": "權(quán)限失效,請(qǐng)重新登錄"})
          ctx.Abort()
          // return
          }

          // 打印userid,既然定義這個(gè)值就必須使用,留下來以備以后的需要
          fmt.Println(claims.UserId)
          if claims.UserId != "" {
          // 如果沒有token沒問題,則退出中間件執(zhí)行下一步
          ctx.Next()
          }
          }

          }
          // 解析字符串token中的信息
          func ParseToken(tokenString string) (*jwt.Token, *claims, error) {
          claims := &claims{}
          token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (i interface{}, err error) {
          return jwtkey, nil
          })
          return token, claims, err
          }

          818679ed8e6d505e9c47e06590fc6253.webp
          此時(shí),刪除本地token:
          404760e58ff89e5f2b9c3dff498fa04a.webp
          刷新頁(yè)面,進(jìn)行token判斷:
          481619409ff19b214ce486026a56ccb1.webp
          此時(shí)接口無(wú)法調(diào)用,這里是因?yàn)槲覀儎h除了本地存儲(chǔ)的token,如果本地有token,但仍然錯(cuò)誤,就是因?yàn)橹皌oken設(shè)定的時(shí)間過期了:
          26f426d26d63016b3de69e4cdc01d2bf.webp
          同時(shí)報(bào)錯(cuò)中顯示為空白,我們需要讓它顯示出來報(bào)錯(cuò)原因,修改兩處:
          (1)將報(bào)錯(cuò)返回的json值return返回:
          6ae356b6dc046004339335eee3dfc99e.webp
          (2)修改前端頁(yè)面的vue攔截信息,我們返回的錯(cuò)誤是msg:
          a180a5c00f4492565f56bf68513d7905.webp
          此時(shí)再次刷新頁(yè)面:
          d1a9cf762edaee677f16c16b1ea68b8a.webp
          既然報(bào)錯(cuò),則跳轉(zhuǎn)到登陸頁(yè)面:
          6d1ce7994350737bed3549bada9c40e5.webp
          刷新頁(yè)面,此時(shí)跳轉(zhuǎn)到登錄頁(yè)面:
          8e57cfe93bcde594da231230c8029b8a.webp
          登錄進(jìn)入頁(yè)面測(cè)試,無(wú)法登錄:
          66c215c7b65b31e13f72791d7e49d274.webp
          這事因?yàn)槲覀兊膖oken判斷中間件,同樣作用于login接口,所以需要進(jìn)行改動(dòng)后端接口路由:
          6ed4ddd048b8d14b50e97560a7223446.webp
          將登錄接口放在token解析中間件上方,中間件就不會(huì)對(duì)登錄接口作用了,只會(huì)作用于下方接口,保存編譯測(cè)試:
          91b4538c5ae4bfa352ece2e68760d950.webp
          到此,登錄的token解析功能實(shí)現(xiàn)。

          3.解析token總結(jié)

          只要我們確立好實(shí)現(xiàn)token驗(yàn)證的過程方向后就可以完成這個(gè)功能。登錄的token驗(yàn)證過程非常簡(jiǎn)單,就是調(diào)用接口→發(fā)送token→接收token→判斷token→將token判斷結(jié)果傳給前端→如已登錄運(yùn)行接口(若未登錄跳轉(zhuǎn)登錄頁(yè))→返回?cái)?shù)據(jù),我們的搭建過程就是對(duì)每個(gè)步驟進(jìn)行逐一尋找找方法、解決。

          4.導(dǎo)航守衛(wèi)

          此時(shí)我們只要調(diào)用接口就會(huì)解析token,但是進(jìn)入沒有接口的頁(yè)面就不會(huì)跳轉(zhuǎn)。如果我們不想讓用戶在不登陸的狀態(tài)下訪問我們的所有網(wǎng)頁(yè),就需要在前端也設(shè)置token判斷,做到只要不登錄,就無(wú)法訪問所有頁(yè)面。
          這里我們就需要用到Vue的導(dǎo)航守衛(wèi)。
          大家可以查看我之前的文章進(jìn)行設(shè)置,純前端操作,不涉及后端:

          技能學(xué)習(xí):學(xué)習(xí)使用Node.js + Vue.js,開發(fā)前端全棧網(wǎng)站-12-4.登陸的前端vue-router路由驗(yàn)證(導(dǎo)航守衛(wèi))

          到此就完成了一個(gè)簡(jiǎn)單的全棧項(xiàng)目,大家可以參照學(xué)習(xí)過程研究更多功能,下篇文章將admin端放入server端,通過server端進(jìn)行項(xiàng)目的訪問,將前后端分離狀態(tài)合并成一個(gè)完整的獨(dú)立項(xiàng)目(改為待上線模式,還是前后端分離)。

          更多設(shè)計(jì)、功能的學(xué)習(xí)經(jīng)驗(yàn),大家也可以去我的公眾號(hào)查看!

          ————


          瀏覽 50
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久热免费视频在线观看 | 亚洲最大黄色 | 婷婷激情五月天丁香 | 国产高清无码黄 | 桃色成人网|