前言:
什么是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