1

我正在使用 jersey rest webservice 以及带有 RSA 签名令牌功能的 JWT 进行身份验证。我能够成功创建令牌并将其发送到前端。现在,在我做到这一点之后,我对验证令牌以及识别请求资源的用户感到困惑。

这里有几个问题:

  1. 我是否必须解码在前端收到的 jwt 令牌以检查声明?
  2. 如何识别请求后端资源的用户?

因为在 SO 上的少数帖子中,有些人说不需要在前端解码令牌(检查此链接),而其他站点上的其他示例显示了在前端解码令牌的示例,例如

现在我很困惑如何进一步了解我是否应该在前端实际解码令牌或保持原样?如果是这样,其他示例如何在前端显示解码,如下所示

angular.module('app')
   .factory('Auth', ['$http', '$localStorage', 'urls', function ($http, $localStorage, urls) {
       function urlBase64Decode(str) {
           var output = str.replace('-', '+').replace('_', '/');
           switch (output.length % 4) {
               case 0:
                   break;
               case 2:
                   output += '==';
                   break;
               case 3:
                   output += '=';
                   break;
               default:
                   throw 'Illegal base64url string!';
           }
           return window.atob(output);
       }

       function getClaimsFromToken() {
           var token = $localStorage.token;
           var user = {};
           if (typeof token !== 'undefined') {
               var encoded = token.split('.')[1];
               user = JSON.parse(urlBase64Decode(encoded));
           }
           return user;
       }

我在这里使用的令牌示例:

private void authenticate(String email, String password)
    throws Exception {
try {
    Connection con = DBConnection.getConnection();
    PreparedStatement statement = con.prepareStatement("select USR_PRIMARY_EMAIL, USR_PASSWORD from TBL_USER where USR_PRIMARY_EMAIL=? and USR_PASSWORD=?");
    statement.setString(1, email);
    statement.setString(2, password);
    ResultSet result = statement.executeQuery();
    if (result.next()) {
        System.out.println("User authenticated successfully");

        KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance("RSA");
        keyGenerator.initialize(1024);

        KeyPair kp = keyGenerator.genKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) kp.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) kp.getPrivate();
        JWSSigner signer = new RSASSASigner(privateKey);

        JWTClaimsSet claimsSet = new JWTClaimsSet();
        claimsSet.setSubject("alice");
        claimsSet.setIssuer("https://c2id.com");
        claimsSet.setExpirationTime(new Date(new Date().getTime() + 60 * 1000));

        System.out.println("publicKey is: " + publicKey);
        System.out.println("privateKey is: " + privateKey);
        System.out.println("claimsSet is: " + claimsSet);

        SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.RS256),claimsSet);

        signedJWT.sign(signer);
        token = signedJWT.serialize();
        System.out.println("Token is: " + token);

        signedJWT = SignedJWT.parse(token);

        System.out.println("signedJWT is: " + signedJWT);

        JWSVerifier verifier = new RSASSAVerifier(publicKey);
        assertTrue(signedJWT.verify(verifier));
        assertEquals("alice", signedJWT.getJWTClaimsSet().getSubject());
        assertEquals("https://c2id.com", signedJWT.getJWTClaimsSet().getIssuer());
        assertTrue(new Date().before(signedJWT.getJWTClaimsSet().getExpirationTime()));
    } else {
        System.out.println("User doesn't exist");
    }
} catch (Exception e) {
    System.out.println("DB related Error");
    e.printStackTrace();
}
}

还有一个问题是使用 nimbus+jose_JWT(RSA 签名) 生成的令牌我无法在 angular auth0库中解码。是因为我使用的是公钥吗?

4

1 回答 1

3

我是否必须解码在前端收到的 jwt 令牌以检查声明?

是的。JWT 声明集是 base64URL 编码的 JSON,因此您需要解码才能读取它。


如何识别请求后端资源的用户?

声明是可选的sub,但实际上每个 JWT 提供者都会发布所有带有标识请求者的主题 ID 的令牌。来自 JWT 规范:

“sub”(主题)声明标识了作为 JWT 主题的主体。JWT 中的声明通常是关于主题的陈述。主题值必须在发行者的上下文中限定为本地唯一或全局唯一。此声明的处理通常是特定于应用程序的。“sub”值是包含 StringOrURI 值的区分大小写的字符串。使用此声明是可选的。


还有一个问题是使用 nimbus+jose_JWT(RSA 签名) 生成的令牌我无法在 angular auth0 库中解码。是因为我使用的是公钥吗?

不,所有 JWT 声明集都是 base64URL 编码的 JSON,独立于签名方法,因此您应该能够对其进行解码。

于 2016-01-02T01:51:41.750 回答