V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zhongpingjing
V2EX  ›  Java

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

  •  
  •   zhongpingjing · 2020-10-14 16:45:02 +08:00 · 3017 次点击
    这是一个创建于 1500 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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


    我错了...
    注意这个. value 为 null 是移除
    zhongpingjing
        9
    zhongpingjing  
    OP
       2020-10-14 18:50:51 +08:00
    @qinxi 感谢,通过 debug 发现了,为 null 时不会被校验。
    zhongpingjing
        10
    zhongpingjing  
    OP
       2020-10-14 19:07:24 +08:00
    @czzt1 感谢建议,已经发现问题了,改为手动验证了
    optional
        11
    optional  
       2020-10-14 19:16:00 +08:00
    @ShinChven 去数据库再查一次你就不应该用 jwt,db based session 适合你。
    lijialong1313
        12
    lijialong1313  
       2020-10-15 08:49:02 +08:00
    @optional 无状态怎么 session 好啊,随机生成个值然后服务器记着嘛
    tamer
        13
    tamer  
       2020-10-15 09:11:43 +08:00
    @optional jwt 本身 server 需要一个'数据源'用来做比对,数据库查询获取数据没什么问题
    liuxiaohua
        14
    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
        15
    zhongpingjing  
    OP
       2020-10-15 14:44:11 +08:00
    @liuxiaohua 这是自定义 payload 的内容哈
    optional
        16
    optional  
       2020-10-15 16:01:29 +08:00 via iPhone
    @lijialong1313 再查数据库 和 db based session 有何区别?
    @tamer jwt 不需要, 用 jwt 当 session 用的才需要。
    lijialong1313
        17
    lijialong1313  
       2020-10-16 08:33:42 +08:00
    @optional 它只要不是劣于 session 就可以了。因为 session 是基于 cookies 的,都叫无状态了很少会带 cookies 。
    optional
        18
    optional  
       2020-10-16 09:01:53 +08:00 via iPhone
    @lijialong1313 本质上是一样的,你也可以用随机的 Authorization 当 session id 比 jwt 短多了。
    lijialong1313
        19
    lijialong1313  
       2020-10-16 10:02:57 +08:00
    @optional session 也不短吧,我写过一个 session 是随机生成的,然后 jwt 也用 session,然后也有签名算法和加密算法。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2833 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 08:38 · PVG 16:38 · LAX 00:38 · JFK 03:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.