token介绍
JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种方式,用于在各方之间安全地将信息作为 JSON 对象传输。由于此信息是经过数字签名的,因此可以被验证和信任。可以使用秘密(使用 HMAC 算法)或使用 RSA 或 ECDSA 的公钥/私钥对对 JWT 进行签名。
尽管可以对 JWT 进行加密以提供双方之间的保密性,但我们将重点关注已签名的令牌(signed tokens)。签名的令牌可以验证其中包含的声明的完整性,而加密的令牌则将这些声明隐藏。当使用公钥/私钥对对令牌进行签名时,签名还证明只有持有私钥的一方才是对其进行签名的一方。
Token是一种服务端生成的一串字符串,以作客户端进行请求的一个令牌。当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。 在用户鉴权中,Token可以用来验证用户是否拥有访问系统的权利。对用户进行鉴权,防止非法用户占用网络资源,非法用户接入网络,被骗取关键信息。——来自星火大模型
jwt-go 安装
go get -u github.com/dgrijalva/jwt-go@v3.2.0
生成token
使用 jwt-go 库生成 token,我们需要定义需求(claims),也就是说我们需要通过 jwt 传输的数据。假如我们需要传输 ID 和 Username,我们可以定义 Claims 结构体,其中包含 ID 和 Username 字段,还有在 jwt-go 包预定义的 jwt.StandardClaims。 例如:
type Claims struct {
ID int64
Username string
jwt.StandardClaims
}
使用jwt-go生成token主要用到jwt-go库中的 jwt.NewWithClaims 和 SignedString 这两种方法
jwt.NewWithClaims
func jwt.NewWithClaims(method jwt.SigningMethod, claims jwt.Claims) *jwt.Token
jwt.NewWithClaims 可以根据实例化的Claims结构体来创建token,其中jwt.SigningMethod类型的method包含三种不同的加密算法,分别为:jwt.SigningMethodHS256、
jwt.SigningMethodHS384 和
jwt.SigningMethodHS512
jwt.Claims类型的claims为自定义的claims
SignedString
func (*jwt.Token).SignedString(key interface{}) (string, error)
SignedString 方法根据传入的空接口类型参数 key,返回完整的签名令牌。
示例
func GenerateToken() (string, error) {
nowTime := time.Now()
expireTime := nowTime.Add(300 * time.Second)
issuer := "frank"
claims := MyCustomClaims{
ID: 10001,
Username: "frank",
StandardClaims: jwt.StandardClaims{
ExpiresAt: expireTime.Unix(),
Issuer: issuer,
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256,claims)
return token.SignedString([]byte("golang")) // "golang" 为此例的key,可以换成其他
}
解析token
使用 jwt-go 库解析 token,主要用到 jwt.ParseWithClaims 方法和 Valid 方法
jwt.ParseWithClaims
func jwt.ParseWithClaims(tokenString string, claims jwt.Claims, keyFunc jwt.Keyfunc) (*jwt.Token, error)
jwt.ParseWithClaims 方法用于解析鉴权的声明,返回 *jwt.Token。
Valid
Valid 方法用于校验鉴权的声明。
示例
func ParseToken(token string) (*MyCustomClaims, error) {
tokenClaims, err := jwt.ParseWithClaims(token, &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte("golang"), nil
})
if err != nil {
return nil, err
}
if tokenClaims != nil {
if claims, ok := tokenClaims.Claims.(*MyCustomClaims); ok && tokenClaims.Valid {
return claims, nil
}
}
return nil, err
}