douxian4888 2018-02-03 23:23 采纳率: 0%
浏览 334
已采纳

即使传递了不正确的参数,JWT始终有效

I'm working with the jwt-go library and I've written tests for implementing it in my application. However, no matter what token I create, it is returned as valid. I'm guessing I'm not checking for something. The documentation is out of date because claims no longer support indexing.

This is my application code:

// AuthService - provides authentication
type AuthService struct{}

// CreateToken - signs and encrypts auth token
func (a *AuthService) CreateToken(email, password string) (string, error) {
    token := jwt.New(jwt.SigningMethodHS256)
    token.Claims = buildClaims(email, password)

    tokenString, err := token.SignedString([]byte(os.Getenv("AUTH_SECRET")))
    if err != nil {
        return "", err
    }

    return tokenString, nil
}

// VerifyToken - ensures that the token is valid
func (a *AuthService) VerifyToken(email, password, token string) bool {
    claims := buildClaims(email, password)
    parser := new(jwt.Parser)

    parsedClaims, _ := parser.ParseWithClaims(token, claims, getKey)

    return parsedClaims.Valid
}

func getKey(t *jwt.Token) (interface{}, error) {
    return []byte(os.Getenv("AUTH_SECRET")), nil
}

func buildClaims(email, password string) jwt.Claims {
    claims := make(jwt.MapClaims)

    claims["email"] = email
    claims["password"] = password
    claims["exp"] = time.Now().Add(time.Hour * 24).Unix()
    claims["iat"] = time.Now().Unix()

    return claims
}

And this is the failing test:

func TestAuthToken(t *testing.T) {
    // var err error
    var valid bool

    os.Setenv("AUTH_SECRET", "secret")

    email := "test@test.com"
    password := "password"

    auth := &AuthService{}

    token, err := auth.CreateToken(email, password)
    if err != nil {
        t.Errorf("AuthService failed to create a token: %v", err)
    }

    valid = auth.VerifyToken(email, password, token)
    if !valid {
        t.Errorf("AuthService failed to verify token: %v", err)
    }

    valid = auth.VerifyToken("invalid", "", token)
    fmt.Println(valid)
    if valid {
        t.Error("AuthService verified a bad password")
    }
}

What I do not understand is why the final test would return valid. In fact, I can put anything in the password or the email and they will be considered as valid.

Is it possible that this has something to do with the fact that password and email are not standard claims?

  • 写回答

1条回答 默认 最新

  • dongshike7171 2018-02-04 12:44
    关注

    Yes, it's that because the email and password, are not the part of the standard Claims there is validation method which is used in your example

    func (m MapClaims) Valid() error {
        vErr := new(ValidationError)
        now := TimeFunc().Unix()
    
        if m.VerifyExpiresAt(now, false) == false {
            vErr.Inner = errors.New("Token is expired")
            vErr.Errors |= ValidationErrorExpired
        }
    
        if m.VerifyIssuedAt(now, false) == false {
            vErr.Inner = errors.New("Token used before issued")
            vErr.Errors |= ValidationErrorIssuedAt
        }
    
        if m.VerifyNotBefore(now, false) == false {
            vErr.Inner = errors.New("Token is not valid yet")
            vErr.Errors |= ValidationErrorNotValidYet
        }
    
        if vErr.valid() {
            return nil
        }
    
        return vErr
    }
    

    Do you really need to verifie password and username? Because it's already checked when whole token is passed. But if you anyway wanna check this data you can make some struct

    type CustomClaims struct {
        jwt.StandardClaims
        Email    string `json:"email,omitempty"`
        Password string `json:"password,omitempty"`
    }
    

    which you then can verify in your VerifyToken method token after parsing calims.

    if claims, ok := parsedClaims.Claims.(*CustomClaims); ok {
        if claims.Password != password {
            parsedClaims.Valid = false
        }
        if claims.Email != username {
            parsedClaims.Valid = false
        }
    }
    

    Some other things:

    1. You do not need to build calims in VerifeToken just pass Claims object or pass your own with your custom Valid method which will satisfying interface
    2. For creating token you can use NewWithClaims method
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图