Gin中使用jwt:發放token、中間件鑒權


Gin中使用jwt:發放token、中間件鑒權

jwt,github地址:

https://github.com/dgrijalva/jwt-go/

前端返回結果的token分析:

//eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOjYsImV4cCI6MTYzNzY2Nzk5OCwiaWF0IjoxNjM3MDYzMTk4LCJpc3MiOiJjaGVuZ3FpYW5nIiwic3ViIjoidXNlciB0b2tlbiJ9.nt8K7vxrAT4XXzh0RbtFveQCyt7J4r1XZnVgDNSVjkQ
//token由三部分組成
//加密協議、荷載(程序信息)、前面兩部分+自定義密匙組成的一個哈希值
//使用base64解密保存的信息(分三段進行解密) :  echo eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 | base64 -D

jwt配置:common/jwt.go

package common

import (
	"github.com/dgrijalva/jwt-go"
	"supplierQuerySystemAPICode/model"
	"time"
)

//定義秘鑰
var jwtKey = []byte("*******")

type Claims struct {
	UserId uint
	jwt.StandardClaims
}

//登錄成功之后發放token
func ReleaseToken(user model.User) (string, error) {
	expirationTime := time.Now().Add(7 * 24 * time.Hour) //token的有效期是七天
	claims := &Claims{
		UserId: user.ID,
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expirationTime.Unix(), //token的有效期
			IssuedAt:  time.Now().Unix(), //token發放的時間
			Issuer:    "chengqiang", //作者
			Subject:   "user token", //主題
		},
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	tokenString, err := token.SignedString(jwtKey) //根據前面自定義的jwt秘鑰生成token

	if err != nil {
		//返回生成的錯誤
		return "", err
	}
	//返回成功生成的字符換
	return tokenString, nil
}
//eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOjYsImV4cCI6MTYzNzY2Nzk5OCwiaWF0IjoxNjM3MDYzMTk4LCJpc3MiOiJjaGVuZ3FpYW5nIiwic3ViIjoidXNlciB0b2tlbiJ9.nt8K7vxrAT4XXzh0RbtFveQCyt7J4r1XZnVgDNSVjkQ
//token由三部分組成
//加密協議、荷載(程序信息)、前面兩部分+自定義密匙組成的一個哈希值
//使用base64解密保存的信息(分三段進行解密) :  echo eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 | base64 -D



//解析從前端獲取到的token值
func ParseToken(tokenString string) (*jwt.Token, *Claims, error) {
	claims := &Claims{}
	token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
		return jwtKey, nil
	})
	return token, claims, err
}

中間件判斷前端獲取的請求信息,驗證通過,獲取用戶信息id,存入上下文中

package middleware

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"strings"
	"supplierQuerySystemAPICode/common"
	"supplierQuerySystemAPICode/model"
)
//路由請求中間件,前端必須把token放在請求頭上,對服務器進行請求驗證token成功后,才能訪問后續的請求路由
func AuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 獲取 authorization header:獲取前端傳過來的信息的
		tokenString := c.GetHeader("Authorization")

		fmt.Print("請求token", tokenString)

		//驗證前端傳過來的token格式,不為空,開頭為Bearer
		if tokenString == "" || !strings.HasPrefix(tokenString, "Bearer ") {
			c.JSON(401, gin.H{
				"data": gin.H{

				},
				"meta": gin.H{
					"msg":  "權限不足",
					"code": 401,
				},
			})
			return
		}

		//驗證通過,提取有效部分(除去Bearer)
		tokenString = tokenString[7:] //截取字符
		//解析token:common/jwt.go
		token, claims, err := common.ParseToken(tokenString)
		//解析失敗||解析后的token無效
		if err != nil || !token.Valid {
			c.JSON(401, gin.H{
				"data": gin.H{

				},
				"meta": gin.H{
					"msg":  "權限不足",
					"code": 401,
				},
			})
			return
		}

		//token通過驗證, 獲取claims中的UserID
		userId := claims.UserId
		var user model.User
		//查詢數據庫
		common.DB.First(&user, userId)

		// 驗證用戶是否存在
		if user.ID == 0 {
			c.JSON(401, gin.H{
				"data": gin.H{

				},
				"meta": gin.H{
					"msg":  "權限不足",
					"code": 401,
				},
			})
		}

		//用戶存在 將user信息寫入上下文
		c.Set("user", user)

		c.Next()
	}
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM