JWT

golang 的 JWT 实现

  1. 如何判断 Token 是否可疑:我们在生成Token的时候,可以添加自定义 Claim (身份信息单元),那么我们可以参考网站登录的安全机制,那么我们可以添加一个用户ip的Claim,这样我们生成的Token都会携带用户生成Token时的IP,我们每次验证Token是否有效时,就可以根据客户端来源IP与Token携带的IP进行匹配,如果匹配不上,那么该Token我们就可以认为是可疑的,从而进行黑名单的验证
  2. TokenGenerator 的具体实现

    func (mw *GinJWTMiddleware) TokenGenerator(userID string, data interface{}) (string, time.Time, error) {
       // 根据签名算法创建 token 对象
        token := jwt.New(jwt.GetSigningMethod(mw.SigningAlgorithm))
        // 获取 claims
        claims := token.Claims.(jwt.MapClaims)
    
       // 设置业务中需要的额外信息
        if mw.PayloadFunc != nil {
            for key, value := range mw.PayloadFunc(data) {
                claims[key] = value
            }
        }
    
       // 过期时间
        expire := mw.TimeFunc().UTC().Add(mw.Timeout)
        claims["id"] = userID
        claims["exp"] = expire.Unix()
        claims["orig_iat"] = mw.TimeFunc().Unix()
        // 生成 token 
        tokenString, err := mw.signedString(token) 
        if err != nil {
            return "", time.Time{}, err
        }
    
        return tokenString, expire, nil
    }
  3. 登录阶段

    登录时会调用 Authenticator 注册的方法。

    func (api *API) LoginAuthenticator(ctx *gin.Context) (interface{}, error) {
        var params model.UserParams
        if err := ctx.Bind(&params); err != nil {
            return "", jwt.ErrMissingLoginValues
        }
    
       // 根据用户名获取用户
        user, err := api.App.GetUserByName(params.Username)
        if err != nil {
            return nil, err
        }
    
       // 验证密码
        if user.AuthPassword(params.Password) {
            return *user, nil
        }
    
        return nil, jwt.ErrFailedAuthentication
    }
  4. 在业务 Hander 中可以通过方法 jwt.ExtractClaims(ctx) 来获取 payload 的信息。
  5. 解密 token 的对象叫做 Parser

    type Parser struct {}
    
    // 主要解析方法
    func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) {}

    Parser 除了验证 Token 外,还包括解码 Header 和 Claims 的内容。

posted @ 2020-02-24 17:32  xy秋千  阅读(165)  评论(0)    收藏  举报