Golang 使用 JWT 跨域鉴权
这是我参与「第三届青训营 -后端场」笔记创作活动的第3篇笔记。
01 简介
JWT全称 JSON Web Token是一种跨域认证解决方案,属于一个开放的标准,它规定了一种Token实现方式,目前多用于前后端分离项目和OAuth2.0业务场景下。
本次案例以极简版抖音项目为例,大致介绍下使用方法。
02 步骤
1、安装 jwt
go get github.com/dgrijalva/jwt-go
2、生成 jwt
这个字段可以根据自己的需求自行添加、修改。
// MyClaims 自定义声明结构体并内嵌 jwt.StandardClaims
type MyClaims struct {
Username string `json:"username"`
Password string `json:"password"`
jwt.StandardClaims
}
这里定义了一个秘钥 MySecret ,通过调用 func GenToken(username string, password string) (string, error) 函数使用指定的 MySecret 签名并获得完整的编码后的字符串 token ,这里的返回值就是字符串 token 。
ExpiresAt:过期时间,time.Now().Add(time.Hour * 24).Unix() ,即获取当前时间并加上自定义的的时间,最后通过 Unix() 转换成时间戳。
Issuer:签发人,可以自定义。
// MySecret 定义Secret
var MySecret = []byte("douCheng")
// GenToken 生成JWT
func GenToken(username string, password string) (string, error) {
// 创建一个我们自己的声明
c := MyClaims{
username, // 自定义字段
password,
jwt.StandardClaims{
ExpiresAt: time.Now().Add(time.Hour * 24).Unix(), // 过期时间
Issuer: "douCheng", // 签发人
},
}
// 使用指定的签名方法创建签名对象
token := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
// 使用指定的secret签名并获得完整的编码后的字符串token
return token.SignedString(MySecret)
}
3、解析 jwt
ParseToken 函数:解析字符串 token ,返回对应的刚刚自定义的结构体数据 MyClaims 。
主要使用 jwt.ParseWithClaims() 。
// ParseToken 解析JWT
func ParseToken(tokenString string) (*MyClaims, error) {
// 解析token
token, err := jwt.ParseWithClaims(tokenString, &MyClaims{},
func(token *jwt.Token) (i interface{}, err error) {
return MySecret, nil
})
if err != nil {
return nil, err
}
if claims, ok := token.Claims.(*MyClaims); ok && token.Valid { // 校验token
return claims, nil
}
return nil, errors.New("invalid token")
}
4、验证 token
几乎每个的功能实现都需要验证 token ,如果都调用 ParseToken然后去验证一次未免也太繁琐了,所以这里写一个 TokenIsValid 的函数,每次想验证只调用这一个并返回响应的 model 的结构体数据就好了。这里拿到 claims.username 之后,通过调用数据库查询相应的 model.Userinfo 。
func TokenIsValid(token string) (model.Userinfo, bool) {
var userinfo model.Userinfo
// 是否过期
claims, err := ParseToken(token)
if err != nil {
return userinfo, false
}
// 拿到 claims.username 之后,通过调用数据库查询相应的 model.Userinfo
user, err := dao.Mgr.IsExist(claims.Username)
if err != nil {
log.Println(err)
return userinfo, false
}
if user.Name != claims.Username {
return userinfo, false
}
return user, true
}
03 总结
开头介绍了什么是 JWT、怎么安装 jwt-go 库。然后通过生成 token 和解析 token 、具体验证实例,介绍了大致的过程方法。jwt-go 不仅限于这些,大家可以阅读官方文档进一步了解。
参考资料: