【原】在Golang程序中支持RS256验证的JWT

前言:

什么是JWT就不做介绍了,本文只介绍如何基于JWT做支持RS256验证的Go程序。

几个有用的URL:

  1. https://godoc.org/github.com/dgrijalva/jwt-go#example-Parse–Hmac
  2. https://jwt.io/
  3. 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

发表评论

电子邮件地址不会被公开。 必填项已用*标注