Golang 与 JWT登陆

什么是JWT

JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间以 JSON 方式安全地传输信息。由于此信息是经过数字签名的,因此可以被验证和信任。可以使用HMAC 算法或使用 RSA , ECDSA 的公钥/私钥对对 JWT 进行签名。

工具与技术栈

Golang语言
使用gin框架启动一个服务
使用postman进行请求模拟

JWT使用

实现两个函数

//获取Tokens
func Tokens(c *gin.Context) (string ,error)
//验证token函数
func JwtAuth(c *gin.Context) (string, error)

而一般我们获取tokens会注册在gin的路由中,作为一个接口使用
验证token函数一般是每一次请求都应该进行验证,所以一般会放在middleware中进行使用

实现代码

获取Tokens

func Tokens(c *gin.Context) (string ,error) {
	//解析 Authorization
	splits := strings.Split(c.GetHeader("Authorization"), " ")
	if len(splits) != 2 {
		return "", errors.New("用户名或密码格式错误")
	}

	//base64 解码
	appSecret, err := base64.StdEncoding.DecodeString(splits[1])
	if err != nil {
		return "", err
	}

	fmt.Println(string(appSecret))
	//获得username和password
	parts := strings.Split(string(appSecret), ":")
	if len(parts) != 2 {
		return "", errors.New("用户名或密码格式错误")
	}
	//TODO 通常是username 和password校验
	//生成token
	claims := jwt.StandardClaims{
		Issuer:    parts[0],
		ExpiresAt: time.Now().Add(JwtExpires * time.Second).Unix(),
	}
	token,err := JwtEncode(claims)
	return token, err
}

验证token

func JwtAuth(c *gin.Context) (string, error) {
	claims, err := JwtDecode(strings.ReplaceAll(c.GetHeader("Authorization"), "Bearer ", ""))
	if err != nil {
		return "", err
	}
	fmt.Println(claims)

	//TODO 一般会根据claims.Issuer获取用户信息
	userName := claims.Issuer
	return userName, nil
}

封装函数


const (
	JwtSignKey = "my_sign_key"
	JwtExpires = 60 * 60
)

func JwtDecode(tokenString string) (*jwt.StandardClaims, error) {
	token, err := jwt.ParseWithClaims(tokenString, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, error) {
		return []byte(JwtSignKey), nil
	})
	if err != nil {
		return nil, err
	}
	if claims, ok := token.Claims.(*jwt.StandardClaims); ok {
		return claims, nil
	} else {
		return nil, errors.New("token is not jwt.StandardClaims")
	}
}

func JwtEncode(claims jwt.StandardClaims) (string, error) {
	mySigningKey := []byte(JwtSignKey)
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString(mySigningKey)
}

验证测试

我们使用postman模拟两个接口的使用
所以我们把函数注册路由,并且添加middleware

func token(c *gin.Context) {
	token, err := Access.Tokens(c)
	if err != nil {
		c.JSON(200, err.Error())
		return
	}
	c.JSON(200, token)
}

func getUserName(c *gin.Context) {
	if username, exists := c.Get("username"); exists {
		c.JSON(200, username)
		return
	}
	c.JSON(200, "username not exists")
}
func Register(eng *gin.RouterGroup) {
	eng.GET("/oauth/tokens",token)

	eng.Use(middleware.JwtAuthMiddleware())
	eng.GET("/username",getUserName)
}

启动服务
请求token

其实就是在请求的header添加格式化的数据

只不过postman会将username和passward进行加密编码

把刚才的token以这种方式传递,我这里接口没有做任何事情,只是将用户名进行返回

实际也是固定格式的数据添加到header中

总结

这里没有太多将理论知识,直接用golang实现jwt登陆的基础框架,以及路由注册,中间件使用,以及使用postman调试时验证jwt登陆时如何配置,在实际项目中jwt登陆也是比较常见的一种登陆验证形式。
详情代码
https://github.com/zhaoshoucheng/hodgepodge/blob/main/Access/jwt.go
gin框架使用
https://github.com/zhaoshoucheng/hodgepodge/tree/main/quick_gin

posted @ 2021-11-30 09:16  zscbest  阅读(340)  评论(0编辑  收藏  举报