我的hmacsha256签名验证几乎可以工作,但不完全可以

2vuwiymt  于 2021-07-08  发布在  Java
关注(0)|答案(1)|浏览(471)

我编写了一个方法,将jwt作为请求,并检查签名是否有效。
这是单元测试:

@Test
public void isValid() {
    final JwtValidator jwtValidator = JwtValidator.getInstance();
    final boolean valid = jwtValidator.isValid("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c");
    Assert.isTrue(valid);
}

代码如下:

@SneakyThrows
public boolean isValid(String extractedToken) {
    final String[] tokenParts = extractedToken.split(Pattern.quote("."));
    String header = tokenParts[0];
    String payload = tokenParts[1];
    String signature = tokenParts[2];

    final byte[] calcHmacSha256 = HMAC.calcHmacSha256("your-256-bit-secret".getBytes(), (header+"."+payload).getBytes());

    final String s = Base64.getEncoder().encodeToString(calcHmacSha256);

    System.out.println("'" + signature + "'.equals('"+s+"')");
    return signature.equals(s);
}

日志打印的两个字符串只有2个字符不同,所以我觉得我接近“但不完全”使它工作:

'SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'.equals('SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV/adQssw5c=')

当然有硬编码的值,因为实现并不完整,但我使用的是中的示例值https://jwt.io/ 为了方便使用。
谢谢!
编辑1:

public class JwtValidatorTest {

    @Test
    public void isValid() {
        byte[] header64 = Base64.getEncoder().encode("{\"alg\":\"HS256\",\"typ\":\"JWT\"}".getBytes());
        byte[] payload64 = Base64.getEncoder().encode("{\"sub\":\"1234567890\",\"name\":\"John Doe\",\"iat\":1516239022}".getBytes());

        final byte[] calcHmacSha256 = HMAC.calcHmacSha256("your-256-bit-secret".getBytes(), (header64+"."+payload64).getBytes());
        final String signature64 = Base64.getEncoder().encodeToString(calcHmacSha256);

        final String input = header64 + "." + payload64 + "." + signature64;

        final JwtValidator jwtValidator = JwtValidator.getInstance();

        final boolean valid = jwtValidator.isValid(input);

        Assert.isTrue(valid);
    }
}
mbyulnm0

mbyulnm01#

这种差异只是由这里使用的不同编码造成的。您使用了base64编码,但原始签名是base64url编码的。base64url编码是jwt的标准编码
base64url编码没有填充( = )结尾和人物 + 以及 / 替换为 - 以及 _ .
这应该可以解决问题:

final String s = Base64.getUrlEncoder().encodeToString(calcHmacSha256);

相关问题