Java 使用jwt令牌身份验证识别用户

Java 使用jwt令牌身份验证识别用户,java,angularjs,jersey,jwt,jose4j,Java,Angularjs,Jersey,Jwt,Jose4j,我正在使用jersey rest webservice和JWT以及RSA签名令牌功能进行身份验证。我能够成功地创建令牌并将其发送到前端。现在,在我达到这一点之后,我对验证令牌和识别请求资源的用户感到困惑 这里有几个问题: 我是否必须解码前端接收到的jwt令牌以检查 索赔 如何识别请求后端资源的用户 因为在上的一些帖子中,一些人说不需要解码前端的令牌(),而其他网站上的其他示例显示了解码前端令牌的示例,例如 现在,我很困惑如何进一步,究竟我应该在前端解码令牌,还是让它保持原样?如果是这样,为什么其

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

这里有几个问题:

  • 我是否必须解码前端接收到的jwt令牌以检查 索赔
  • 如何识别请求后端资源的用户
  • 因为在上的一些帖子中,一些人说不需要解码前端的令牌(),而其他网站上的其他示例显示了解码前端令牌的示例,例如

    现在,我很困惑如何进一步,究竟我应该在前端解码令牌,还是让它保持原样?如果是这样,为什么其他示例显示前端解码,如:

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

    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库中解码。是因为我在使用公钥吗

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

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


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

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

    “sub”(subject)索赔确定了作为 JWT的主题。JWT中的声明通常是声明 关于这个话题。subject值的作用域必须为 在发行人的上下文中是本地唯一的,或者是全球唯一的。 本索赔的处理通常是针对具体应用的。这个 “sub”值是包含StringOrURI的区分大小写的字符串 价值此声明的使用是可选的


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


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

    HI Rodrigo。非常感谢你的回答。我现在能够正确解码令牌,但问题是它只返回有效负载信息,如
    sub
    iss
    exp
    ,但没有标题和签名?我是否也需要这些值来标识用户?还要在标题中插入授权信息吗?或者仅仅有效负载信息就足够了?当调用接受JWT的API时,您只需在
    授权
    头中传递整个JWT(例如
    授权:承载eyJ…
    )。JWT库允许您在解码令牌时访问声明集。访问报头通常是不必要的,因为您应该事先知道所期望的签名算法(请参阅)。也没有必要手动访问签名,因为您应该直接使用库的验证方法。
    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();
    }
    }