Java - Auth0 JWT验证 - 这是正确的吗?

use*_*874 6 java rsa jwt auth0

我正在使用Auth0作为身份验证服务来设置REST API.一切都在发挥作用,但在一个相当奇怪的事件发生后,我的信心有点动摇了.

我的实现基于此处的示例代码(RS256部分)和此处.唯一的修改是我投了PublicKey一个RSAPublicKey.

问题是我想肯定验证会在签名错误时失败.我更改了签名的最后一个字符(我们将说"x")并且令牌仍然经过验证. 但是 - 将其切换为"x" 以外的任何字符或原始生成的字符都会导致其按预期失败.

我的怀疑是,这是由于某种填充/编码/解码/ Base64问题,而我刚刚选择了一个具有相同的前n个位或其他东西的字符?当然,这意味着如果要做出成功的"猜测",它将需要包括令牌的剩余四十亿字符 - 这是它存在的全部要点.所以我并不担心令牌是可猜测的 - 我只是确保我已经正确地实现了验证的要点.

import com.auth0.jwk.Jwk;
import com.auth0.jwk.JwkException;
import com.auth0.jwk.JwkProvider;
import com.auth0.jwk.UrlJwkProvider;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.security.interfaces.RSAPublicKey;

public class Application {
    public static void main(String[] args) {

        try {
            JwkProvider provider = new UrlJwkProvider("<my-provider>");
            Jwk jwk = provider.get("<my-key-id>");

            String token = "<some-token-passed-from-client>";
            RSAPublicKey publicKey = (RSAPublicKey) jwk.getPublicKey();

            Algorithm algorithm = Algorithm.RSA256(publicKey, null);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer("<my-issuer>")
                    .build();
            DecodedJWT jwt = verifier.verify(token);

        } catch (JWTVerificationException exception) {
            System.out.println("JWT Exception: " + exception.getMessage());
        } catch (JwkException e) {
            e.printStackTrace();
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

use*_*461 0

看看JWT 示例(下面的屏幕截图)即可。

该令牌由 3 个不同颜色的部分组成:

  • 标头:有关令牌的元数据,包括所使用的算法。未签名且未验证。
  • Payload:令牌的内容(用户声明)。签字并核实。
  • 签名:令牌的签名。

特别是标头没有签名,它们几乎可以包含任何内容并且可以更改。尽管如果令牌被破坏(例如错误的算法值),则令牌将无法被解码。

有规则将所有这些数据编码、填充和序列化在一起,请参阅规范。可以在令牌中添加/删除/编辑几个字节,并且仍然具有有效的令牌,尽管略有不同(修改的填充或标头)。然而,不可能改变令牌的有效负载,这才是重要的。

JWT 库提供单独的函数来从令牌中提取信息,例如get_unverified_headers()get_claims(),避免任何潜在的混淆。假设,如果有人不小心从标头而不是有效负载中读取了用户标识符,这将是一个严重的漏洞,因为它可以自由更改。

JWT 令牌示例