一 JWT介绍
JWT 英文名是 Json Web Token ,是一种用于通信双方之间传递安全信息的简洁的、URL安全的表述性声明规范,经常用在跨域身份验证。
JWT 以 JSON 对象的形式安全传递信息。因为存在数字签名,因此所传递的信息是安全的。
一个JWT Token就像这样:
eyJhbGci0iJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoyODAx0DcyNzQ40DMyMzU4NSwiZ
XhwIjoxNTk0NTQwMjkxLCJpc3MiOiJibHV1YmVsbCJ9.1k_ZrAtYGCeZhK3iupHxP1kgjBJzQTVTtX0iZYFx9wU
它是由.分隔的三部分组成,这三部分依次是:
头部(Header)
负载(Payload)
签名(Signature)
头部和负载以jSON形式存在,这就是JWT中的JSON,三部分的内容都分别单独经过了Base64编
码,以.拼接成一个JWT Token。
二 JWT优缺点
JWT拥有基于Token的会话管理方式所拥有的一切优势,不依赖Cookie,使得其可以防止CSRF攻
击,也能在禁用Cookie的浏览器环境中正常运行。
而JWT的最大优势是服务端不再需要存储Session,使得服务端认证鉴权业务可以方便扩展,避免存储
Session所需要引入的Redis等组件,降低了系统架构复杂度。但这也是JWT最大的劣势,由于有效期
存储在Token中,JWT Token一旦签发,就会在有效期内一直可用,无法在服务端废止,当用户进行登
出操作,只能依赖客户端删除掉本地存储的JWT Token,如果需要禁用用户,单纯使用JWT就无法做到。
三 JWT使用
1. 导包和数据定义
package token import ( "account/config/redis" "errors" "fmt" "github.com/dgrijalva/jwt-go" "time" ) // MyClaims 自定义声明结构体并内嵌jwt.StandardClaims // jwt包自带的jwt.StandardClaims只包含了官方字段 // 我们这里需要额外记录一个username字段,所以要自定义结构体 // 如果想要保存更多信息,都可以添加到这个结构体中 type MyClaims struct { UserName string `json:"username"` jwt.StandardClaims } const TokenExpireDuration = time.Hour * 2 var MySecret = []byte("Account")
2.生成JWT
// GenToken 生成JWT func GenToken(UserName string) (string, error) { // 创建一个我们自己的声明 c := MyClaims{ UserName, // 自定义字段 jwt.StandardClaims{ ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(), // 过期时间 Issuer: "Account", // 签发人 }, } // 使用指定的签名方法创建签名对象 token := jwt.NewWithClaims(jwt.SigningMethodHS256, c) // 使用指定的secret签名并获得完整的编码后的字符串token return token.SignedString(MySecret) }
3.解析JWT
// ParseToken 解析JWT func ParseToken(tokenString string) (*MyClaims, error) { // 解析token var mc = new(MyClaims) token, err := jwt.ParseWithClaims(tokenString, mc, func(token *jwt.Token) (i interface{}, err error) { return MySecret, nil }) if err != nil { return nil, err } if token.Valid { // 校验token return mc, nil } return nil, errors.New("invalid token") }
4.完整代码
package token import ( "account/config/redis" "errors" "fmt" "github.com/dgrijalva/jwt-go" "time" ) // MyClaims 自定义声明结构体并内嵌jwt.StandardClaims // jwt包自带的jwt.StandardClaims只包含了官方字段 // 我们这里需要额外记录一个username字段,所以要自定义结构体 // 如果想要保存更多信息,都可以添加到这个结构体中 type MyClaims struct { UserName string `json:"username"` jwt.StandardClaims } const TokenExpireDuration = time.Hour * 2 var MySecret = []byte("Account") // GenToken 生成JWT func GenToken(UserName string) (string, error) { // 创建一个我们自己的声明 c := MyClaims{ UserName, // 自定义字段 jwt.StandardClaims{ ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(), // 过期时间 Issuer: "Account", // 签发人 }, } // 使用指定的签名方法创建签名对象 token := jwt.NewWithClaims(jwt.SigningMethodHS256, c) // 使用指定的secret签名并获得完整的编码后的字符串token return token.SignedString(MySecret) } // ParseToken 解析JWT func ParseToken(tokenString string) (*MyClaims, error) { // 解析token var mc = new(MyClaims) token, err := jwt.ParseWithClaims(tokenString, mc, func(token *jwt.Token) (i interface{}, err error) { return MySecret, nil }) if err != nil { return nil, err } if token.Valid { // 校验token return mc, nil } return nil, errors.New("invalid token") }
四 最后
- 至此,go-micro微服务JWT跨域认证工作就正式完成。
- 接下来就开始公用函数的代码编写了,希望大家关注博主和关注专栏,第一时间获取最新内容,每篇博客都干货满满。