jwt

51 阅读2分钟

what?

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

JWT是由三段信息构成的,将这三段信息文本用.链接一起就构成了Jwt字符串。就像这样:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

具体介绍看www.jianshu.com/p/576dbf44b…

how?

JWT Token 进行认证的流程如下图: 具体可以分为四步:

  • 客户端使用用户名和密码请求登录。
  • 服务端收到请求后,会去验证用户名和密码。如果用户名和密码跟数据库记录不一致,则验证失败;如果一致则验证通过,服务端会签发一个 Token 返回给客户端。
  • 客户端收到请求后会将 Token 缓存起来,比如放在浏览器 Cookie 中或者 LocalStorage 中,之后每次请求都会携带该 Token。
  • 服务端收到请求后,会验证请求中的 Token,验证通过则进行业务逻辑处理,处理完后返回处理后的结果。

golang中使用

一般在需要登陆态的接口前面增减校验中间件,校验完毕还可以把一些用户信息通过context传递给用户方法

func JwtAuthMiddleware() func(c *gin.Context) {
   return func(c *gin.Context) {
      fmt.Println("JwtAuthMiddleware enter")
      //Authorization 后面格式为 bearer [token] 中间有个空格
      tokenStr := c.Request.Header.Get("Authorization")
      if tokenStr == "" {
         c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "用户不存在"})
         c.Abort()
         return
      }
      tokenSlice := strings.SplitN(tokenStr, " ", 2)
      if len(tokenSlice) != 2 || tokenSlice[0] != "Bearer" {
         c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "token格式错误"})
         c.Abort()
         return
      }
      //校验token
      claims, err := jwt.ParseWithClaims(tokenSlice[1])
      if err != nil {
         c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "token校验失败"})
         c.Abort()
         return
      }
      uidStr := claims["uid"].(string)
      //判断缓存中有jwt,防止用户已经登出
      if !redis.IsJwtCacheExist(c, redis.GetJwtCacheKey(uidStr)) {
         c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "用户未登陆"})
         c.Abort()
         return
      }
      // 后续的处理函数可以用过c.Get("uid")来获取当前请求的用户信息
      c.Set("uid", claims["uid"])
      c.Next()
   }
}

注意:因为jwt一旦颁发就不能撤回,所以中途如果用户退出登陆需要后端自己去实现注销逻辑,这里的办法就是在后端颁发token的同时在缓存中也存一份,过期时间就是token的exp时间,如果中途登出就删除缓存,所以中间件中除了jwt的既定校验,还需要判断缓存是否存在,不存在说明已经登出,校验同样失败

测试

登陆之后获取信息

curl -H "Authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxIiwiZXhwIjoxNjY2NjgyOTE1fQ.fnr1F15mJN60l529RuGDkdDgKM3050eJ2retYzMt5tw" -H "Content-Type:application/json"  http://localhost:8080/v1/user/huangsha

如果不加下面这个认证就会校验失败

-H "Authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxIiwiZXhwIjoxNjY2NjgyOTE1fQ.fnr1F15mJN60l529RuGDkdDgKM3050eJ2retYzMt5tw"

引用 www.jianshu.com/p/576dbf44b…