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