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

时间:2016-01-01 20:11:59

标签: java angularjs jersey jwt jose4j

我正在使用泽西休息网络服务以及带有RSA签名令牌功能的JWT进行身份验证。我能够成功创建令牌并将其发送到前端。在我实现了这一点之后,我对于验证令牌以及识别用户请求资源感到困惑。

这里几乎没有问题:

  1. 我是否必须解码前端收到的jwt令牌才能检查 权利要求?
  2. 如何识别在后端请求资源的用户?
  3. 因为SO上的帖子很少,有些人说它不需要解码前端的令牌(check this link),而其他网站上的其他示例则显示了解码前端令牌的示例,例如{{ 3}}

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

    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签名)生成的令牌我无法在角度this库中解码。是因为我使用公钥吗?

1 个答案:

答案 0 :(得分:3)

  

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

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

  

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

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

  

" sub" (主题)声明确定了作为的主体      JWT的主题。 JWT中的声明通常是声明      关于这个问题。主题值必须是作用域      在发行人的背景下本地独特或全球独特。      该权利要求的处理通常是特定于应用的。该      "子" value是包含StringOrURI的区分大小写的字符串      值。使用此声明是可选的。

  

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

没有。所有JWT声明集都是base64URL编码的JSON,与签名方法无关,因此您应该能够对其进行解码。