设为首页 - 加入收藏 潍坊站长网 (http://www.0536zz.com)- 国内知名站长资讯网站,提供最新最全的站长资讯,创业经验,网站建设等!
热搜: 2018 2019 redis 建设
当前位置: 首页 > 运营中心 > 建站资源 > 优化 > 正文

Golang不到100行实现一套灵活的JWT库

发布时间:2019-10-20 14:13 所属栏目:[优化] 来源:Golang全栈
导读:【大咖·来了 第7期】10月24日晚8点观看《智能导购对话机器人实践》 JWT 全 chen JSON Web Tokens 现在被广泛的应用于各种前后端分离的场景,他比传统的 Token Session 方式,更具灵活性。 当然网上也有很多开源的 JWT 库,非常之多,开源组织也提供了官方
【大咖·来了 第7期】10月24日晚8点观看《智能导购对话机器人实践》

JWT 全 chen JSON Web Tokens 现在被广泛的应用于各种前后端分离的场景,他比传统的 Token Session 方式,更具灵活性。

当然网上也有很多开源的 JWT 库,非常之多,开源组织也提供了官方的库。

Golang不到100行实现一套灵活的JWT库

可以访问这网址去下载:

  • https://jwt.io

但是如果我们知其然而不知其所以然的使用,难免会有很多问题。

所以这次分享下,我最近自己写的一个 JWT 库,代码已经上传到 github 上了,地址如下:

  • https://github.com/liu578101804/go-tool/tree/master/jwt

相比出名的 JWT 库来说,我没有任何优势,只是作为学习使用,欢迎大家指正其中的不足。

下面就给大家说下我的实现思路吧。

JWT 的原理

我们要实现 JWT 算法就得先了解他的原理,我尽量用剪短的话去解释:

JWT 算法输出的数据是一串包含 header(头信息).payload(内容).signature(签名) 的一段字符串。

来一段真实的 JWT 生成的字符串:

  1. eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c?

是不是豁然开朗了,这串字符串又叫 token ,因为这串 token 里面包含了验证需要的信息,相比传统的 session 需要到服务器里面去取验证的信息,更加的灵活独立。

因为他不依赖 session 这种传统的存储,别用在分布式服务器里面有着很大的优势。

当然他也有缺点,最头痛就这 2 点:

  • 不可控。一旦签发出去的 token 将无法提前让他销毁,不像传统的,我可以把我 session 里面的 token 删了下次过来,token 就失效了。当然这也不是没办法解决,在整个体系里面加入黑名单机制就行,只是稍微麻烦了点。
  • 信息相对传统的 session 数据量和隐私性没那么好。因为 token 一般都不建议特别长,所以 payload 承载的数据量是有限的。同时字符串里面的 payload 是可以被解密的,所以存在一定性的被破译风险(当然你可以使用比较难破译的算法去降低这个风险)。

算法组成

JWT 的算法组成很简单,只需要 一个可逆的加密算法去加密 header(头信息).payload(内容),一个不可逆的算法去对前面这部分内容进行加密签名生成 signature(签名) 就行。

如果我们用不同的加密算法组合便形成了不同的 JWT 加密算法。比如:

  • HS256 (HMAC + SHA-256)
  • RS256 (RSA + SHA-256)

当然还有很多,你可以自己去组合,我们将写的这个库支持你自定义。

具体实现

下面就开始进入代码实现阶段了:

说下我的设计思路,Golang 他有一个天然的优势就是支持把函数作为变量传入,我们便可以根据这一特性把加密部分让调用者去实现,我们把实现主体就行,这样便我们的 JWT 便非常灵活了。

我们要写的主体代码去掉注释空行不到 100 行。

jwt.go

  1. package?jwt?
  2. ?
  3. import?(?
  4. ????"encoding/json"?
  5. ????"strings"?
  6. ????"fmt"?
  7. )?
  8. ?
  9. //声明一个标准的JWT接口?
  10. type?IJwt?interface?{?
  11. ????//设置头部?
  12. ????SetHeader(string)?
  13. ????//设置签名算法?
  14. ????SetSignFunc(SignFunc)?
  15. ????//设置编码算法?
  16. ????SetEncodeFunc(EncodeFunc)?
  17. ?
  18. ????//写入body?
  19. ????WriteBody(map[string]interface{})?
  20. ?
  21. ????//生成jwt?
  22. ????CreateJwtString()?(string,error)?
  23. ????//验证jwt?
  24. ????CheckJwtString(string)?bool?
  25. }?
  26. ?
  27. //规范header的格式?
  28. type?Header?struct?{?
  29. ????Type????string??`json:"type"`?
  30. ????Alg?????string??`json:"alg"`?
  31. }?
  32. ?
  33. //签名算法?
  34. type?SignFunc?func([]byte)?string?
  35. //编码算法?
  36. type?EncodeFunc?func([]byte)?string?
  37. ?
  38. ?
  39. //声明一个结构图?去实现?标准的JWT接口?
  40. type?Jwt?struct?{?
  41. ????Header??????Header?
  42. ????Body????????map[string]interface{}?
  43. ?
  44. ????signFun?????SignFunc?
  45. ????encodeFun???EncodeFunc?
  46. }?
  47. ?
  48. //设置头部信息,说明你使用的签名算法?
  49. func?(j?*Jwt)?SetHeader(headerType?string){?
  50. ????j.Header?=??Header{?
  51. ????????Type:?"JWT",?
  52. ????????Alg:?headerType,?
  53. ????}?
  54. }?
  55. ?
  56. //设置签名算法?
  57. func?(j?*Jwt)?SetSignFunc(signFunc?SignFunc)?{?
  58. ????j.signFun?=?signFunc?
  59. }?
  60. ?
  61. //设置对?header?和?body?的加密算法?
  62. func?(j?*Jwt)?SetEncodeFunc(encodeFunc?EncodeFunc)?{?
  63. ????j.encodeFun?=?encodeFunc?
  64. }?
  65. ?
  66. //写入要加密的内容?
  67. func?(j?*Jwt)?WriteBody(body?map[string]interface{})?{?
  68. ????j.Body?=?body?
  69. }?
  70. ?
  71. //生成token?
  72. func?(j?*Jwt)?CreateJwtString()?(string,error)?{?
  73. ????//编码header?
  74. ????headerByte,err?:=?json.Marshal(j.Header)?
  75. ????if?err?!=?nil?{?
  76. ????????return?"",err?
  77. ????}?
  78. ????headerStr?:=?j.encodeFun(headerByte)?
  79. ?
  80. ????//编码body?
  81. ????bodyByte,err?:=?json.Marshal(j.Body)?
  82. ????if?err?!=?nil?{?
  83. ????????return?"",err?
  84. ????}?
  85. ????bodyStr?:=?j.encodeFun(bodyByte)?
  86. ?
  87. ????//签名?
  88. ????signByte?:=?j.signFun([]byte(string(headerStr)+"."+string(bodyStr)))?
  89. ?
  90. ????return?fmt.Sprintf("%s.%s.%s",headerStr,bodyStr,signByte),nil?
  91. }?
  92. ?
  93. //验证?token?是否合规?
  94. func?(j?*Jwt)?CheckJwtString(input?string)?bool??{?
  95. ????arr?:=?strings.Split(input,".")?
  96. ????//格式是否正确?
  97. ????if?len(arr)?!=?3?{?
  98. ????????return?false?
  99. ????}?
  100. ????//签名?
  101. ????signByte?:=?j.signFun([]byte(string(arr[0])+"."+string(arr[1])))?
  102. ????if?string(signByte)?!=?arr[2]?{?
  103. ????????return?false?
  104. ????}?
  105. ????return?true?
  106. }?

这个文件就已经把 JWT 的核心给写好了,现在只需要根据你想要的加密算法进行填充就好了。

【免责声明】本站内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。

网友评论
推荐文章