温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何用Golang实现一套灵活的JWT库

发布时间:2021-11-24 14:14:41 来源:亿速云 阅读:224 作者:柒染 栏目:编程语言

如何用Golang实现一套灵活的JWT库,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

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

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

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

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

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

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

JWT 的原理

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

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

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

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

package jwt  import (     "encoding/json"     "strings"     "fmt" )  //声明一个标准的JWT接口 type IJwt interface {     //设置头部     SetHeader(string)     //设置签名算法     SetSignFunc(SignFunc)     //设置编码算法     SetEncodeFunc(EncodeFunc)      //写入body     WriteBody(map[string]interface{})      //生成jwt     CreateJwtString() (string,error)     //验证jwt     CheckJwtString(string) bool }  //规范header的格式 type Header struct {     Type    string  `json:"type"`     Alg     string  `json:"alg"` }  //签名算法 type SignFunc func([]byte) string //编码算法 type EncodeFunc func([]byte) string   //声明一个结构图 去实现 标准的JWT接口 type Jwt struct {     Header      Header     Body        map[string]interface{}      signFun     SignFunc     encodeFun   EncodeFunc }  //设置头部信息,说明你使用的签名算法 func (j *Jwt) SetHeader(headerType string){     j.Header =  Header{         Type: "JWT",         Alg: headerType,     } }  //设置签名算法 func (j *Jwt) SetSignFunc(signFunc SignFunc) {     j.signFun = signFunc }  //设置对 header 和 body 的加密算法 func (j *Jwt) SetEncodeFunc(encodeFunc EncodeFunc) {     j.encodeFun = encodeFunc }  //写入要加密的内容 func (j *Jwt) WriteBody(body map[string]interface{}) {     j.Body = body }  //生成token func (j *Jwt) CreateJwtString() (string,error) {     //编码header     headerByte,err := json.Marshal(j.Header)     if err != nil {         return "",err     }     headerStr := j.encodeFun(headerByte)      //编码body     bodyByte,err := json.Marshal(j.Body)     if err != nil {         return "",err     }     bodyStr := j.encodeFun(bodyByte)      //签名     signByte := j.signFun([]byte(string(headerStr)+"."+string(bodyStr)))      return fmt.Sprintf("%s.%s.%s",headerStr,bodyStr,signByte),nil }  //验证 token 是否合规 func (j *Jwt) CheckJwtString(input string) bool  {     arr := strings.Split(input,".")     //格式是否正确     if len(arr) != 3 {         return false     }     //签名     signByte := j.signFun([]byte(string(arr[0])+"."+string(arr[1])))     if string(signByte) != arr[2] {         return false     }     return true }

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

下面我们就去实现一个最简单的 RS256 算法,新建一个 bs.go 文件,内容如下:

package jwt  import (     "crypto/sha256"     "encoding/base64"     "fmt" )  func NewRS256() IJwt {      jwtM := Jwt{}      //Sha256     jwtM.SetSignFunc(func(bytes []byte) string {         h := sha256.New()         h.Write(bytes)         return fmt.Sprintf("%x",h.Sum(nil))     })      //base64     jwtM.SetEncodeFunc(func(bytes []byte) string {         return base64.URLEncoding.EncodeToString(bytes)     })      return &jwtM }

我这里 header 和 payload 采用 base64 去加密,签名采用 sha256 当然这种算法生成的 JWT  很容易被人串改模仿,不能用于生产的。

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI