RSA非对称加密的是对签名的加密,不是对jwt的头部,荷载加密,头部和荷载用的时base64加密,从jwt官网就可以知道
token是通过拼字符串拼在一起的。
从而得出结论:
1.荷载里面可以放自定义的数据,但是不能放敏感数据。
如上图,就算拿着token到这里,可以看见header,payload,但是左下角显示的时无效的签名Invalid Signature,因为没有放入公钥
输入对应的公钥,就可以看见,完成了校验。从而就可以知道公钥和密钥的使用方式和场景。
非对称加密,前提需要公钥和密钥,它们是成对出现
一般密钥用来签名,公钥用来校验,这一般是两个文件存放的数据。生成密钥可以使用golang的rsa库,公钥可以直接从密钥中获取。
其实在这里,我们可以选择每次生成新token时都重新生成一堆密钥公钥,然后将公钥发布到需要更新公钥的系统中,也可以始终只用一对公钥密钥。这在分布式的系统中很有帮助。产生钥匙对的系统只用将公钥发布给各个系统即可。因为它们只需要做校验功能。
func CreateKeys() (*rsa.PrivateKey, rsa.PublicKey) {
privateKey, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
panic(err)
}
publicKey := privateKey.PublicKey
return privateKey, publicKey
}
这里我们将已经生成的密钥存入了一个private.key文件
func GetPrivateKey(privateKeyFilePath string) *rsa.PrivateKey {
file, err := os.Open(filePath)
if err != nil {
fmt.Errorf("%v", err)
}
pkBytes, err := ioutil.ReadAll(file)
if err != nil {
fmt.Errorf("%v", err)
}
key, err := jwt.ParseRSAPrivateKeyFromPEM(pkBytes)
if err != nil {
fmt.Errorf("cannot parse private key>%v", err)
}
return key
}
func GetPublicKeyByPrivateKey(privateKeyFilePath string) *rsa.PublicKey {
privateKey := GetPrivateKey(filePath)
publicKey := privateKey.PublicKey
return &publicKey
}
func (j *JWT) CreateToken(claims request.CustomClaims) (string, error) {
//选择签名算法,传入荷载
token := jwt.NewWithClaims(jwt.SigningMethodRS512, claims)
//获取密钥
privateKey := GetPrivateKey("./source/keyFile/private.key")
//签名
tokenStr, err := token.SignedString(privateKey)
return tokenStr, err
}
这里从密钥获取公钥是因为,这是在jwt签名的系统中进行的解析,就无所谓了
// 解析 token
func (j *JWT) ParseToken(tokenString string) (*request.CustomClaims, error) {
publicKey := GetPublicKeyByPrivateKey("密钥数据文件路径")
token, err := jwt.ParseWithClaims(tokenString, &request.CustomClaims{}, func(token *jwt.Token) (i interface{}, e error) {
return publicKey, nil
})
if err != nil {
if ve, ok := err.(*jwt.ValidationError); ok {
if ve.Errors&jwt.ValidationErrorMalformed != 0 {
return nil, TokenMalformed
} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
// Token is expired
return nil, TokenExpired
} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
return nil, TokenNotValidYet
} else {
return nil, TokenInvalid
}
}
}
if token != nil {
if claims, ok := token.Claims.(*request.CustomClaims); ok && token.Valid {
return claims, nil
}
return nil, TokenInvalid
} else {
return nil, TokenInvalid
}
}