(进阶)goland+jwt实现用户登录获取token

我是不会赢的 · · 1632 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

(进阶)golang+gin+jwt实现用户登录获取token

  • 1.获取token

    POST请求参数

    {
        "name":"xj",
        "pwd":"xj123456"
    }
    

    golang api router:

    
    // 获取Token
    router.POST("/api/getToken", service.GetApiTokenService)
    

    service:

    
    //请求参数结构体
    type GetTokenRequestParam struct {
      Name string `json:"Name"`
      Pwd  string `json:"Pwd"`
    }
    
    //自定义密钥
    var tokenApiSecret = "itxj980420"
    //获取token
    func GetTokenService(c *gin.Context) {
      reqModel := GetTokenRequestParam{}
      errByBind := c.Bind(&reqModel)
      if errByBind != nil {
          c.JSON(http.StatusOK, gin.H{
              "code":    http.StatusBadRequest,
              "message": "失败",
              "token":   "",
          })
          return
      }
      //参数非空校验
      if common.IsEmpty(reqModel.Name) || common.IsEmpty(reqModel.Pwd) {
          c.JSON(http.StatusOK, gin.H{
              "code":    http.StatusBadRequest,
              "message": "账号、密码不能为空!!!",
              "token":   "",
          })
          return
      }
      //TODO 添加其他校验如账号密码校验;签名校验等其他自定义参数校验
    
      //jwt token header 法加密
      token := jwt.New(jwt.SigningMethodHS256)
      //jwt claims 载荷
      //jti:该jwt的唯一标识
      //iss:该jwt的签发者
      //iat:该jwt的签发时间
      //aud:该jwt的接收者
      //sub:该jwt的面向的用户
      //nbf:该jwt的生效时间,可不设置,若设置,一定要大于当前Unix UTC,否则token将会延迟生效
      //  exp:该jwt的过期时间 Unix()
      claims := make(jwt.MapClaims)
      claims["jti"] = reqModel.Name + reqModel.Pwd + strconv.Itoa(int(time.Now().Unix()))
      claims["iss"] = "itxj"
      claims["iat"] = time.Now()
      claims["aud"] = reqModel.Name
      claims["sub"] = reqModel.Name
      claims["nbf"] = time.Now().Unix()
      claims["exp"] = time.Now().Add(time.Hour * time.Duration(24)).Unix()
      //Payload载荷
      token.Claims = claims
      //密钥加密
      tokenStr, errBySignToken := token.SignedString([]byte(tokenApiSecret))
        //token 生成失败
      if errBySignToken != nil {
          c.JSON(http.StatusOK, gin.H{
              "code":    http.StatusUnauthorized,
              "message": "Error while signing the token!",
              "token":   "",
          })
          return
      }
      //success
      c.JSON(http.StatusOK, gin.H{
          "code":    http.StatusOK,
          "message": "Success!",
          "token":   tokenStr,
      })
      return
    }
    
  • 2.路由中间件校验token

    GET 请求

    http://ip:port/api/validateToken/:key

    Param: key:载荷中的key

//请求
header 里面
    "Token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ4aiIsImV4cCI6MTU3Nzg2NjU1NiwiaWF0IjoiMjAxOS0xMi0zMVQxNjoxNTo1NS4zNDUyODkrMDg6MDAiLCJpc3MiOiJpdHhqIiwianRpIjoieGppdHhqMTU3Nzc4MDE1NCIsIm5iZiI6MTU3Nzc4MDE1NSwic3ViIjoieGoifQ.zg0FtD4Ovk0GysPSxn2IZfFkvA6KmqbczDPu9zQDFk4"

gin router api

    router.GET("/api/validateToken/:key", service.ValidateTokenService(), service.TestValidateTokenService)

路由中间件—-:校验token是否有效

//路由中间件校验token
func ValidateTokenService() gin.HandlerFunc {

    return func(c *gin.Context) {

        token, err := request.ParseFromRequest(c.Request, request.AuthorizationHeaderExtractor, func(token *jwt.Token) (i interface{}, e error) {
            return []byte(tokenApiSecret), nil
        })
        if err != nil {
            c.Abort()
            c.JSON(http.StatusOK, gin.H{
                "code":    http.StatusUnauthorized,
                "message": "fail",
                "error":   "Unauthorized!",
            })
            return
        }
        if !token.Valid {
            c.Abort()
            c.JSON(http.StatusOK, gin.H{
                "code":    http.StatusUnauthorized,
                "message": "fail",
                "error":   "An invalid Token!",
            })
            return
        }
        c.Next()
    }
}

service:

//获取token中的账号
func TestValidateTokenService(c *gin.Context) {
    sub := c.Param("key")
    token, _ := GetTokenFromRequest(c)
    claimsVal := GetValueFromTokenClaims(sub, token.Claims)
    c.JSON(http.StatusOK, gin.H{
        "code":      http.StatusOK,
        "message":   "成功",
        "claimsVal": claimsVal,
    })
    return
}

//从请求头中获取token
func GetTokenFromRequest(c *gin.Context) (token *jwt.Token, err error) {
    token, err = request.ParseFromRequest(c.Request, request.AuthorizationHeaderExtractor,
        func(token *jwt.Token) (interface{}, error) {
            return []byte(tokenApiSecret), nil
        })
    return token, err
}

//根据key从载荷中获取数据
func GetValueFromTokenClaims(key string, claims jwt.Claims) string {
    v := reflect.ValueOf(claims)
    if v.Kind() == reflect.Map {
        for _, k := range v.MapKeys() {
            value := v.MapIndex(k)

            if fmt.Sprintf("%s", k.Interface()) == key {
                return fmt.Sprintf("%v", value.Interface())
            }
        }
    }
    return ""
}


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:我是不会赢的

查看原文:(进阶)goland+jwt实现用户登录获取token

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1632 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传