前言:
什么是JWT就不做介绍了,本文只介绍如何基于JWT做支持RS256验证的Go程序。
几个有用的URL:
https://godoc.org/github.com/dgrijalva/jwt-go#example-Parse–Hmac
https://jwt.io/
https://github.com/dgrijalva/jwt-go
其实官网提供了很多各种语言的SDK,直接拿来用就好(本文选用的是github.com/dgrijalva/jwt-go),但查询资料途中,大部分都是HMAC验证(作为对称加密的一种,总有种不安的感觉),于是根据自己的实践,编写本文。
准备工作:
此处基于Linux环境下,需要openssl以及Go环境的支持
生成一个私钥证书(做签发用)
# openssl genrsa -out private.key 2048
基于私钥生成一个公钥证书(做验证用)
# openssl rsa -in private.key -pubout > public.key
开始写代码了:(以下代码经过删减与修改,主要是调用github.com/dgrijalva/jwt-go项目)
import (
...
jwt "github.com/dgrijalva/jwt-go"
...
)
var (
publicKey *rsa.PublicKey
privateKey *rsa.PrivateKey
)
func init() {
publicKeyByte, err := ioutil.ReadFile("公钥的路径/public.key")
if err != nil {
log.Println(err.Error())
}
publicKey, err = jwt.ParseRSAPublicKeyFromPEM(publicKeyByte)
privateKeyByte, err := ioutil.ReadFile("私钥的路径/private.key")
if err != nil {
log.Println(err.Error())
}
privateKey, _ = jwt.ParseRSAPrivateKeyFromPEM(privateKeyByte)
}
// createToken 生成一个RS256验证的Token
// Token里面包括的值,可以自己根据情况添加,
func createToken() (tokenStr string, err error) {
token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims{
"iat": time.Now().Unix(), // Token颁发时间
"nbf": time.Now().Unix(), // Token生效时间
"exp": time.Now().Add(time.Hour * 24).Unix(), // Token过期时间,目前是24小时
"iss": "liwenbin.com", // 颁发者
"sub": "AuthToken", // 主题
// "role": "guest", // 角色(附加)
})
return token.SignedString(privateKey)
}
// getSubFromToken 获取Token的主题(也可以更改获取其他值)
// 参数tokenStr指的是 从客户端传来的待验证Token
// 验证Token过程中,如果Token生成过程中,指定了iat与exp参数值,将会自动根据时间戳进行时间验证
func getSubFromToken(tokenStr string) (sub string, err error) {
// 基于公钥验证Token合法性
token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
// 基于JWT的第一部分中的alg字段值进行一次验证
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
return nil, errors.New("验证Token的加密类型错误")
}
return publicKey, nil
})
if err != nil {
return
}
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
return claims["sub"].(string), nil
}
return "", errors.New("Token无效或者无对应值")
}
这样,就搞定了,注意要把公私钥的路径确定好哈。
生成的Token分为3个部分(均基于BASE64编码,以“.”区分),第一个部分是定义,第二个部分是你生成Token时设置的各项值,第三个是签名。
最后再次感谢项目:github.com/dgrijalva/jwt-go