JWT前言
JWT是JSON Web Token的缩写。JWT本身没有定义任何技术实现,它只是定义了一种基于Token的会话管理的规则,涵盖Token需要包含的标准内容和Token的生成过程。
JWT组成
JWT由.分割的三部分组成,这三部分依次是:
头部(Header)
作用:记录令牌类型、签名算法等 例如:{“alg":“HS256”,“type”,"JWT}
负载(Payload)
作用:携带一些用户信息 例如{“userId”:“1”,“username”:“mayikt”}
签名(Signature)
作用:防止Token被篡改、确保安全性 例如 计算出来的签名,一个字符串
头部和负载以json形式存在,这就是JWT中的JSON,三部分的内容都分别单独经过了Base64编码,以.拼接成一个JWT Token。
JWT在go中的使用
1.导包
import ( "errors" "github.com/dgrijalva/jwt-go" "time" )
2.定义结构体和一些基本信息
// MyClaims 自定义声明结构体并内嵌jwt.StandardClaims // jwt包自带的jwt.StandardClaims只包含了官方字段 // 我们这里需要额外记录一个username字段,所以要自定义结构体 // 如果想要保存更多信息,都可以添加到这个结构体中 type MyClaims struct { ID int `json:"id"` Email string `json:"email"` jwt.StandardClaims } const TokenExpireDuration = time.Hour * 2 var MySecret = []byte("qi66")
3.生成JWT
// GenToken 生成JWT func GenToken(ID int, Email string) (string, error) { // 创建一个我们自己的声明 c := MyClaims{ ID, Email, // 自定义字段 jwt.StandardClaims{ ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(), // 过期时间 Issuer: "qi66", // 签发人 }, } // 使用指定的签名方法创建签名对象 token := jwt.NewWithClaims(jwt.SigningMethodHS256, c) // 使用指定的secret签名并获得完整的编码后的字符串token return token.SignedString(MySecret) }
4.解析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") }
使用JWT优缺点
JWT拥有基于Token的会话管理方式所拥有的一切优势,不依赖Cookie,使得其可以防止CSRF攻击,也能在禁用Cookie的浏览器环境中正常运行。
而JWT的最大优势是服务端不再需要存储Session,使得服务端认证鉴权业务可以方便扩展,避免存储Session所需要引入的Redis等组件,降低了系统架构复杂度。但这也是JWT最大的劣势,由于有效期存储在Token中,JWT Token-旦签发,就会在有效期内-直可用,无法在服务端废止,当用户进行登出操作,只能依赖客户端删除掉本地存储的JWT Token,如果需要禁用用户,单纯使用JWT就无法做到了。