经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Go语言 » 查看文章
Go语言学习之golang-jwt/jwt的教程分享
来源:jb51  时间:2023/1/16 9:16:23  对本文有异议

一、介绍

jwt是 json web token的简称。

go使用jwt目前,主流使用的jwt库是golang-jwt/jwt

1.1 如何安装

  1. go get -u github.com/golang-jwt/jwt/v4

1.2 import到项目里

  1. import "github.com/golang-jwt/jwt/v4"

1.3 主流2类加密算法介绍

加密算法代表算法加解密
对称加密算法(hash加密) hsaHS256(最常用), HS384, HS512期望[]byte用于签名和验证的值
非对称签名方法 rsaRS256(最常用), RS384,RS512rsa.PrivateKey用于签名和*rsa.PublicKey验证

二、代码实现 -对称加密 hsa(hash加密)

2.1 加密生成token

我们使用 NewWithClaims(method SigningMethod, claims Claims) *Token来生成token,官方的源码如下

  1. // NewWithClaims creates a new Token with the specified signing method and claims.
  2. func NewWithClaims(method SigningMethod, claims Claims) *Token {
  3. return &Token{
  4. Header: map[string]interface{}{
  5. "typ": "JWT",
  6. "alg": method.Alg(),
  7. },
  8. Claims: claims,
  9. Method: method,
  10. }
  11. }

其中我们需要 传入一个 SigningMethod 加密算法,以及一个 Claims,需要加密的内容。

SigningMethod 我们这里使用 hsa256 哈希加盟

Claims 我们封装一个 UserClaims 如下

我们调用NewWithClaims生成token代码如下:

  1. func TestHs256(t *testing.T) {
  2. type User struct {
  3. Id int64
  4. Name string
  5. }
  6. type UserClaims struct {
  7. User User
  8. jwt.RegisteredClaims
  9. }
  10. // 1 jwt.NewWithClaims生成token
  11. user := User{
  12. Id: 101,
  13. Name: "hisheng",
  14. }
  15. userClaims := UserClaims{
  16. User: user,
  17. RegisteredClaims: jwt.RegisteredClaims{},
  18. }
  19. token := jwt.NewWithClaims(jwt.SigningMethodHS256, userClaims)
  20.  
  21. // 2 把token加密
  22. mySigningKey := []byte("ushjlwmwnwht")
  23. ss, err := token.SignedString(mySigningKey)
  24. t.Log(ss, err)
  25. }

生成token分为两部分

1.使用jwt.NewWithClaims生产jwt.ToKen

2.把jwt.ToKen加密(这里我们需要添加一个加密key,使用base64url加密)

最后我们就得到了加密后的token,可以用来给客户端使用。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VyIjp7IklkIjoxMDEsIk5hbWUiOiJoaXNoZW5nIn19.ij1kWID03f_CiELe0fPLZJ-Y64dkf2nDE-f6nGERBSE

token令牌由三部分组成,由.分隔。

前两部分是 JSON 对象,已经过base64url编码。

最后一部分是签名,以相同的方式编码。

2.2 解密token得到原始数据

我们使用官方的jwt.ParseWithClaims()来解密token,官方文档源代码如下:

  1. func TestHs256Parse(t *testing.T) {
  2. tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VyIjp7IklkIjoxMDEsIk5hbWUiOiJoaXNoZW5nIn19.ij1kWID03f_CiELe0fPLZJ-Y64dkf2nDE-f6nGERBSE"
  3.  
  4. type User struct {
  5. Id int64
  6. Name string
  7. }
  8. type UserClaims struct {
  9. User User
  10. jwt.RegisteredClaims
  11. }
  12.  
  13. token, err := jwt.ParseWithClaims(tokenString, &UserClaims{}, func(token *jwt.Token) (interface{}, error) {
  14. return []byte("ushjlwmwnwht"), nil
  15. })
  16.  
  17. if userClaims, ok := token.Claims.(*UserClaims); ok && token.Valid {
  18. t.Log(userClaims, userClaims.RegisteredClaims.Issuer)
  19. } else {
  20. t.Log(err)
  21. }
  22. }

jwt.ParseWithClaims是parser.ParseWithClaims封装,可以自己再封装一个parser,上面的代码可以用下面的代码代替。

  1. func TestHs256Parse2(t *testing.T) {
  2. tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VyIjp7IklkIjoxMDEsIk5hbWUiOiJoaXNoZW5nIn19.ij1kWID03f_CiELe0fPLZJ-Y64dkf2nDE-f6nGERBSE"
  3.  
  4. type User struct {
  5. Id int64
  6. Name string
  7. }
  8. type UserClaims struct {
  9. User User
  10. jwt.RegisteredClaims
  11. }
  12.  
  13. parser := jwt.NewParser()
  14. token, err := parser.ParseWithClaims(tokenString, &UserClaims{}, func(token *jwt.Token) (interface{}, error) {
  15. return []byte("ushjlwmwnwht"), nil
  16. })
  17.  
  18. if userClaims, ok := token.Claims.(*UserClaims); ok && token.Valid {
  19. t.Log(userClaims, userClaims.RegisteredClaims.Issuer)
  20. } else {
  21. t.Log(err)
  22. }
  23. }

我们在 parser := jwt.NewParser()的时候,可以带上参数,比如parser := jwt.NewParser(WithoutClaimsValidation)// 跳过声明验证(验证过期时间、发表时间、在此之前时间)

三、代码实现 -非对称加密 rsa(我们这里使用rsa256)

2.1 生成 rsa 私钥和公钥

生成私钥

openssl genrsa -out private-key.pem

生成公钥

openssl rsa -in private-key.pem -pubout -out public-key.pem

2.2 加密生成token

  1. func TestRs256(t *testing.T) {
  2. type User struct {
  3. Id int64
  4. Name string
  5. }
  6. type UserClaims struct {
  7. User User
  8. jwt.RegisteredClaims
  9. }
  10. // 1 jwt.NewWithClaims生成token
  11. user := User{
  12. Id: 101,
  13. Name: "hisheng",
  14. }
  15. userClaims := UserClaims{
  16. User: user,
  17. RegisteredClaims: jwt.RegisteredClaims{},
  18. }
  19.  
  20. // Read Private Key
  21. privateKeyDataPem, err := ioutil.ReadFile("private-key.pem")
  22. if err != nil {
  23. log.Fatal(err)
  24. }
  25. // ParseRSAPrivateKeyFromPEM
  26. privateKeyData, err := jwt.ParseRSAPrivateKeyFromPEM(privateKeyDataPem)
  27. if err != nil {
  28. log.Fatal(err)
  29. }
  30. // 2 把token加密
  31. token, err := jwt.NewWithClaims(jwt.SigningMethodRS256, userClaims).SignedString(privateKeyData)
  32. t.Log(token, err)
  33. }

2.2 解密token

  1. func TestRs256Parse(t *testing.T) {
  2. tokenString := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VyIjp7IklkIjoxMDEsIk5hbWUiOiJoaXNoZW5nIn19.GOS-d7iwaLDCSaSsBpArbtH-3JlD1KFNoJeyZjQ6Xv4XySo599WY784mVj-rR9kxtLYmkdAG3dPG9am6NZubHBLYWDi9b1w5gXcC7o3nAZirFGgS7bwf-7DmEetwUWzJZe-QXr1CIiVyHPU2ZCketYkIqgMGixVNfxfS5pJ5LhiUM_7J9Zlf5Kq15P9Y7U35Nu25-UXGgs-BHvH-Db6PJ4vHZq-dla_yuqRN276JBxdc24SEnML_iOHmgXVOXEWjtC_p6LmsP0VGMqwXAHN4FH0XbMzpQtTQKJgskggI41T1Ruzb9zpzJdmiL2DkeMgbvc0xVzV3CjM_AA5cUqcZaQ"
  3. type User struct {
  4. Id int64
  5. Name string
  6. }
  7. type UserClaims struct {
  8. User User
  9. jwt.RegisteredClaims
  10. }
  11.  
  12. token, err := jwt.ParseWithClaims(tokenString, &UserClaims{}, func(token *jwt.Token) (interface{}, error) {
  13. // Read public Key
  14. publicKeyDataPem, err := ioutil.ReadFile("public-key.pem")
  15. if err != nil {
  16. log.Fatal(err)
  17. }
  18. // ParseRSAPublicKeyFromPEM
  19. return jwt.ParseRSAPublicKeyFromPEM(publicKeyDataPem)
  20. })
  21.  
  22. if userClaims, ok := token.Claims.(*UserClaims); ok && token.Valid {
  23. t.Log(userClaims, userClaims.RegisteredClaims.Issuer)
  24. } else {
  25. t.Log(err)
  26. }
  27.  
  28. }

到此这篇关于Go语言学习之golang-jwt/jwt的教程分享的文章就介绍到这了,更多相关Go语言  golang-jwt/jwt内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号