Go JWT学习笔记,核心代码解析

2 篇文章 0 订阅
0 篇文章 0 订阅

对JWT中的核心代码,逐步解析学习

package jwt

import (
	"errors"
	"fmt"
	"time"
	"github.com/dgrijalva/jwt-go"
)
//注意下方的User其实应该定义在module数据模型里 这里定义支付辅助显示一下下
type User struct {
	name string
	Password string
	juese	string
	shouji	string
}
//验证与解密当中的密匙设置的复杂一点,
//viper.GetString会设置这个值(32byte长度)
var AppSecret = "guwen-0208"
//发行网站发行人的意思,
//我的备注:这个值会被viper.GetString重写
var AppIss = "github.com/libragen/felix"

//自定义payload结构体,不建议直接使用 dgrijalva/jwt-go `jwt.StandardClaims`结构体.因为他的payload包含的用户信息太少.
//我的备注:自己的结构体结合jwt框架里的结构体,形成新的结构体来存放信息
type userStdClaims struct {
	jwt.StandardClaims
	*User
}
//实现 `type Claims interface` 的 `Valid() error` 方法,自定义校验内容,
//我的备注:自定义一个函数验证差事,发行人错误等等情况,是代码简洁
func (c userStdClaims) Valid() (err error) {
	/*
	特别注意,下面的c.VerifyExpiresAt方法和c.VerifyIssuer方法都是jwt框架里
	jwt.StandardClaims结构体的方法,继承到了userStdClaims上面
	*/
	//检查一下超时没有,超时就返回错误
	if c.VerifyExpiresAt(time.Now().Unix(), true) == false {
		return  errors.New("token is expired")
	}
	//检查一下发行方正确,令牌的发行方错误
	if !c.VerifyIssuer(AppIss, true) {
		return  errors.New("token's issuer is wrong")
	}
	//检查用户ID是否有效,invalid user in jwt
	if c.User.Id < 1 {
		return errors.New("invalid user in jwt")
	}
	return
}
//登录生成token令牌,其中m是数据模型当中定义的用户结构体,d是超时时间使用time时间即可,比如一年这样写time.Hour*24*365
func jwtGenerateToken(m *User,d time.Duration) (string, error) {
	//清空密码,防止密码泄露
	m.Password = ""
	//设置超时时间,当前时间+超时时间
	expireTime := time.Now().Add(d)
	//设置jwt当中类似用户对象StandardClaims
	stdClaims := jwt.StandardClaims{
		ExpiresAt: expireTime.Unix(),//过期时间,int64类型
		IssuedAt:  time.Now().Unix(),//发现人时间,int64类型
		Id:        fmt.Sprintf("%d", m.Id),//用户ID字符串类型
		Issuer:    AppIss,//发行人,字符串类型
	}
	//实例我们定义的userStdClaims这个结合我们和框架的结构体
	uClaims := userStdClaims{
		StandardClaims: stdClaims,
		User:           m,
	}
	//通过加密方式jwt.SigningMethodHS256加密用户结构体uClaims
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, uClaims)
	// Sign and get the complete encoded token as a string using the secret
	//	使用密钥签名并以字符串形式获取完整的编码令牌
	tokenString, err := token.SignedString([]byte(AppSecret))
	return tokenString, err
}

//解析用户登录当中携带的token信息,解密并返回用户对象User,接受参数字符串形式的token
//JwtParseUser 解析payload的内容,得到用户信息
func JwtParseUser(tokenString string) (*User, error) {
	if tokenString == "" {
		//返回错误,在授权持有者中未发现令牌
		return nil, errors.New("no token is found in Authorization Bearer")
	}
	//设置一个空的userStdClaims接受返回来token中携带的信息
	claims := userStdClaims{}
	//
	//解析token,函数接受三个参数
	//第一个,未解密的token字符串
	//第二个,之前定义的空的userStdClaims对象来接受返回信息
	//第三个一个函数,我们称之为keyFunc函数,将接收解析后的令牌,并返回用于验证的密钥
	_, err := jwt.ParseWithClaims(tokenString, &claims, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHS256); !ok {
			/* 加密方式错误
				意想不到的签名方法,说明token中加密方式和咱们之前加密的方式有出入
				Header通常由两部分组成:令牌的类型,即JWT。和常用的散列算法,如HMAC SHA256或RSA
				{
				  "alg": "HS256",
				  "typ": "JWT"
				}
				咱们生成的时候使用的SHA256加密方式即jwt.SigningMethodHS256,正常是不会出这个错误的
			*/
			return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
		}
		//返回加密当初设置的秘钥
		return []byte(AppSecret), nil
	})
	//解析未发生错误
	if err != nil {
		return nil, err
	}
	return claims.User, err
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值