今天在使用 jwt 的时候遇到一点疑问,没有想明白,来请教一下各位大佬

2020-10-14 16:45:02 +08:00
 zhongpingjing

token 在签发后,校验的时候发现,payload 部分的内容如果有值,但是传参为 null 时却能校验通过

具体案例如下

token 解析后 payload 的内容

{
    "institutionId":10,
    "id":1,
    "isAdmin":true,
    "exp":1603180144
}

institutionId 为 10,但是校验的时候,institutionId 输入 null 却能够通过,institutionId 为其他数字就不会通过。这是为什么?这是个 bug 吗?

我想为 null 时,如果与 payload 的内容不一致时校验无法通过,应该怎么做?

测试代码

public static void main(String[] args) {
    String password = "$2a$10$G2GVQwHC1ankbyEu3nSAS.gWosqEyzg5pAzFbbxa9gLHhtgBq7DJ.";
    String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpbnN0aXR1dGlvbklkIjoxMCwiaWQiOjEsImlzQWRtaW4iOnRydWUsImV4cCI6MTYwMzE4MDE0NH0.9d1W50_xnfU4kT0-YWYUkPV-gM8GWa_-U6nCbuEnC84";
    boolean verify1 = verify(token, password,null);
    System.out.println(verify1); // true  这里我期待的结果是 false,应该怎么做
    boolean verify2 = verify(token, password,1L);
    System.out.println(verify2); // false
    boolean verify3 = verify(token, password,10L);
    System.out.println(verify3); // true
}

检验方法

public static boolean verify(String token,String password,Long institutionId) {
    try {
        Algorithm algorithm = Algorithm.HMAC256(password);
        JWTVerifier verifier = JWT.require(algorithm)
            .withClaim("institutionId",institutionId)
            .build();
        verifier.verify(token);
        return true;
    } catch (Exception exception) {
        return false;
    }
}

jwt 库

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.8.1</version>
</dependency>
2843 次点击
所在节点    Java
19 条回复
qinxi
2020-10-14 17:30:31 +08:00
只校验签名, 一致则可信 ,本来就不校验具体属性的值
zhongpingjing
2020-10-14 17:32:10 +08:00
@qinxi 但是传入参数不为 null 的时候,又校验不通过
qinxi
2020-10-14 17:32:52 +08:00
https://jwt.io/ 体验一下. 三部分数据分别修改一下看 最终的 jwt 变化规律
qinxi
2020-10-14 17:36:20 +08:00
@zhongpingjing #2 没用过你这个 auth0 的库..不知道这个校验的是什么
ShinChven
2020-10-14 17:37:41 +08:00
一般要取出数据,如 id,再去数据库里面查询一次,而不是直仅用 jwt 本身校验。
czzt1
2020-10-14 17:38:40 +08:00
payload 里的内容一般还是自己再去校验,而不是通过 jwt 校验,jwt 只负责签名和到期校验就可以了
qinxi
2020-10-14 17:41:16 +08:00
查到了
代码 com.auth0.jwt.JWTVerifier#verifyClaims 写了校验规则

他这个校验具体内容 switch case 里面有写
qinxi
2020-10-14 17:49:12 +08:00
private void requireClaim(String name, Object value) {
if (value == null) {
this.claims.remove(name);
} else {
this.claims.put(name, value);
}
}


我错了...
注意这个. value 为 null 是移除
zhongpingjing
2020-10-14 18:50:51 +08:00
@qinxi 感谢,通过 debug 发现了,为 null 时不会被校验。
zhongpingjing
2020-10-14 19:07:24 +08:00
@czzt1 感谢建议,已经发现问题了,改为手动验证了
optional
2020-10-14 19:16:00 +08:00
@ShinChven 去数据库再查一次你就不应该用 jwt,db based session 适合你。
lijialong1313
2020-10-15 08:49:02 +08:00
@optional 无状态怎么 session 好啊,随机生成个值然后服务器记着嘛
tamer
2020-10-15 09:11:43 +08:00
@optional jwt 本身 server 需要一个'数据源'用来做比对,数据库查询获取数据没什么问题
liuxiaohua
2020-10-15 14:14:53 +08:00
我也看到了,这个 institutionId 是设置什么,我发现我没设置
private void requireClaim(String name, Object value) {
if (value == null) {
this.claims.remove(name);
} else {
this.claims.put(name, value);
}
}
zhongpingjing
2020-10-15 14:44:11 +08:00
@liuxiaohua 这是自定义 payload 的内容哈
optional
2020-10-15 16:01:29 +08:00
@lijialong1313 再查数据库 和 db based session 有何区别?
@tamer jwt 不需要, 用 jwt 当 session 用的才需要。
lijialong1313
2020-10-16 08:33:42 +08:00
@optional 它只要不是劣于 session 就可以了。因为 session 是基于 cookies 的,都叫无状态了很少会带 cookies 。
optional
2020-10-16 09:01:53 +08:00
@lijialong1313 本质上是一样的,你也可以用随机的 Authorization 当 session id 比 jwt 短多了。
lijialong1313
2020-10-16 10:02:57 +08:00
@optional session 也不短吧,我写过一个 session 是随机生成的,然后 jwt 也用 session,然后也有签名算法和加密算法。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/714908

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX