JWT签名与本地计算的签名不匹配

时间:2017-02-22 16:47:10

标签: java web token jwt

我正在使用

JwtBuilder builder = Jwts.builder()
                    .setId(user.getEmail())
                    .signWith(signatureAlgorithm, signingKey);

然后创建一个令牌

Jwts.parser().setSigningKey(secret).parse(token);

进行身份验证。当我在JUnit测试中运行它时,它工作正常。但是,当我通过REST调用验证作为标头传递的令牌时,身份验证会因SignatureException而失败。我已经在HTTP调用的两端验证了令牌,并且令牌字符串是相同的。创建/认证的代码是静态的,因此,每一方的秘密都是相同的。任何线索

6 个答案:

答案 0 :(得分:8)

每次重新加载服务器时,

static Key secret = MacProvider.generateKey();都会生成一个新的随机密钥,因为在加载类时会初始化静态变量

这意味着如果您发出JWT,只有在服务器不重启时它才有效。您获得的SignatureException是因为签名密钥不同

您需要在第一代后存储签名密钥secret.getEncoded(),并在模块启动时加载

答案 1 :(得分:2)

我遇到了同样的问题,我注意到在源代码中,只要他们转换签名密钥,它们就会明确指定UTF-8编码。我尝试更改编码同时解码令牌:

 private Jws<Claims> decodeToken(String token) {
        return Jwts.parser()
                .setSigningKey(securityProperties.getTokenSecret().getBytes(Charset.forName("UTF-8")))
                .parseClaimsJws(token);
 }

在签署令牌时:

private String getSignedToken(UserDetailsAdapter user, List<String> roles, byte[] signingKey) {
        return Jwts.builder()
                .signWith(Keys.hmacShaKeyFor(signingKey), SignatureAlgorithm.HS512)
                .setHeaderParam("typ", securityProperties.getTokenType())
                .setIssuer(guiServerSecurityProperties.getTokenIssuer())
                .setAudience(guiServerSecurityProperties.getTokenAudience())
                .setSubject(user.getUsername())
                .setExpiration(new Date(System.currentTimeMillis() + 864000000))
                .claim("rol", roles)
                .compact();
    }

这是唯一为我解决此问题的方法。

答案 2 :(得分:1)

我有类似的问题。在我的情况下,两个键都相同,但是由于某种原因,我在引号内收到了令牌(例如"Syasda.da3das.aDjty6"而不是Syasda.da3das.aDjty6)。

我花了很多时间来实现这一点,因为在大多数时候,在jwt.io上进行测试时,我只是手动复制令牌而没有括号来进行验证。

token = token.replace("\"",""); 

删除这些引号为我解决了这个问题。希望这也会对其他人有所帮助。

答案 3 :(得分:1)

可能存在两种类型的问题:

    每次运行功能Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);时,
  1. secretKeyFor都会生成一个不同的随机密钥。因此,如果您想生成一个常量密钥,请尝试使用此密钥
 public SecretKey generalKey(){
        String stringKey = Global.JWT_SECRET;
        byte[] encodedKey =Base64.decodeBase64(stringKey);
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length,
                "HmacSHA512");
        return key;
    }
  1. 在我的代码中,我收到了由ajax传输的令牌,并且使用JSON.stringify()将javasript对象转换为字符串,该字符串将其他配额包装在原始字符串上,尝试消除配额为{{3} } 说过。

答案 4 :(得分:0)

我有类似的问题。就我而言,这是错误的令牌验证。我将符号设置为字节:

.signWith(SignatureAlgorithm.HS512, jwtConfig.getSecret().getBytes())

但是当我解析令牌并设置signKey时,我将其设置为字符串,而不是字节:

Jwts.parser().setSigningKey(signingKey).parseClaimsJws(this.token)

在检查令牌时也要经常检查引号和空格,令牌的开头/结尾经常会出现多余的空格/引号(使用trim()方法)

答案 5 :(得分:0)

我解决了在URL REST端点中修改HOST的问题。它有一个错误的主机,该主机返回了未经授权的HTTP 401错误。