golang入门笔记——jwt

什么是JWT

jwt全称(JSON WEB TOKEN),是一种后台不做存储的前端身份验证的工具。分为三部分:Header、Claims、Signature

如何创建一个JWT

func NewWithClaims(method SigningMethod, claims Claims) *Token {
	return &Token{
		Header: map[string]interface{}{
			"typ": "JWT",
			"alg": method.Alg(),
		},
		Claims: claims,
		Method: method,
	}
}
//method是token签发的方法,claims是实现Claims接口的结构体,
type StandardClaims struct {
	Audience  string `json:"aud,omitempty"`
	ExpiresAt int64  `json:"exp,omitempty"`//过期时间
	Id        string `json:"jti,omitempty"`
	IssuedAt  int64  `json:"iat,omitempty"`
	Issuer    string `json:"iss,omitempty"`//签发人
	NotBefore int64  `json:"nbf,omitempty"`//什么时间开始生效
	Subject   string `json:"sub,omitempty"`
}

生成Token

type MyClaims struct{
	Username string`json:"username"`
	jwt.StandardClaims
}
func CreateToken()(string,error){
myclaim:=MyClaims{
	Username:"zyj",
	StandardClaims:jwt.StandardClaims{
	NotBefore:time.Now().Unix()-60, //当前时间一分钟之前生效 
	ExpiresAt:time.Now().Unix()+60*60*2, //两个小时后过期
	Issuer:"zyj",
}
}
//生成token
token:=jwt.NewWithClains(jwt.SigningMethodHS256,myclaim)
//token:=jwt.NewWithClains(jwt.SigningMethodHS256,jwt.MapClaims{
//	"exp":time.Now().Unix()+5,
//	"iss":"zyj",
//	"nbf":time.Now().Unix()+5,
//	"username":"zyj",
//})
mySigningKey:=[]byte("Come on!")//加密key
return token.SignedString(mySigningKey)
if err!=nil{
fmt.Println("err:",err)
return
}

解析Token

token,err:=jwt.ParseWithClaims(token,claims,func)
 token:我们拿到的token字符串
 我们用哪个claims结构体发的 这里就传入哪个结构体
 func:一个特殊的回调函数 需要固定接受*Token类型指针 返回一个i和err,i为我们的密钥

token是一个jwtToken类型的数据 我们需要的就是其中的Claims
对Claims进行断言 然后进行取用即可
func ParserToken(s string)(*MyClaims,error){
//解析token
token,err:=jwt.ParseWithClaims(s,&MyClaims{},func(token *jwt.Token)(interface{},error){
return mySigningKey,nil
})
return token.Claims.(*MyClaims),err
}

jwt作为gin框架中的中间件使用

package middleware

import (
	"errors"
	"ginblog/utils"
	"ginblog/utils/errmsg"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"net/http"
	"strings"
)

type JWT struct {
	JwtKey []byte
}

func NewJWT() *JWT {
	return &JWT{
		[]byte(utils.JwtKey),
	}
}

type MyClaims struct {
	Username string `json:"username"`
	jwt.StandardClaims
}

// 定义错误
var (
	TokenExpired     error = errors.New("Token已过期,请重新登录")
	TokenNotValidYet error = errors.New("Token无效,请重新登录")
	TokenMalformed   error = errors.New("Token不正确,请重新登录")
	TokenInvalid     error = errors.New("这不是一个token,请重新登录")
)

// CreateToken 生成token
func (j *JWT) CreateToken(claims MyClaims) (string, error) {
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString(j.JwtKey)
}

// ParserToken 解析token
func (j *JWT) ParserToken(tokenString string) (*MyClaims, error) {
	token, err := jwt.ParseWithClaims(tokenString, &MyClaims{}, func(token *jwt.Token) (interface{}, error) {
		return j.JwtKey, nil
	})
	
	if err != nil {
		if ve, ok := err.(*jwt.ValidationError); ok {
			if ve.Errors&jwt.ValidationErrorMalformed != 0 {
				return nil, TokenMalformed
			} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
				// Token is expired
				return nil, TokenExpired
			} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
				return nil, TokenNotValidYet
			} else {
				return nil, TokenInvalid
			}
		}
	}
	
	if token != nil {
		if claims, ok := token.Claims.(*MyClaims); ok && token.Valid {
			return claims, nil
		}
		return nil, TokenInvalid
	}
	
	return nil, TokenInvalid
}

// JwtToken jwt中间件
func JwtToken() gin.HandlerFunc {
	return func(c *gin.Context) {
		var code int
		tokenHeader := c.Request.Header.Get("Authorization")
		if tokenHeader == "" {
			code = errmsg.ERROR_TOKEN_EXIST
			c.JSON(http.StatusOK, gin.H{
				"status":  code,
				"message": errmsg.GetErrMsg(code),
			})
			c.Abort()
			return
		}
		
		checkToken := strings.Split(tokenHeader, " ")
		if len(checkToken) == 0 {
			c.JSON(http.StatusOK, gin.H{
				"status":  code,
				"message": errmsg.GetErrMsg(code),
			})
			c.Abort()
			return
		}
		
		if len(checkToken) != 2 || checkToken[0] != "Bearer" {
			c.JSON(http.StatusOK, gin.H{
				"status":  code,
				"message": errmsg.GetErrMsg(code),
			})
			c.Abort()
			return
		}
		
		j := NewJWT()
		// 解析token
		claims, err := j.ParserToken(checkToken[1])
		if err != nil {
			if err == TokenExpired {
				c.JSON(http.StatusOK, gin.H{
					"status":  errmsg.ERROR,
					"message": "token授权已过期,请重新登录",
					"data":    nil,
				})
				c.Abort()
				return
			}
			// 其他错误
			c.JSON(http.StatusOK, gin.H{
				"status":  errmsg.ERROR,
				"message": err.Error(),
				"data":    nil,
			})
			c.Abort()
			return
		}
		
		c.Set("username", claims)
		c.Next()
	}
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值