可以使用带有jwt和rs256以及auth0的java吗?

时间:2017-07-20 17:03:54

标签: java spring-boot jwt

这是我在尝试验证jwt令牌时遇到的异常: RSA公钥仅支持RSAPublicKeySpec和X509EncodedKeySpec

我正在使用com.nimbusds.jose。

这是doFilter方法:

    @Override
    public void doFilter(final ServletRequest req,
                         final ServletResponse res,
                         final FilterChain chain) throws IOException, ServletException {


        final HttpServletRequest request = (HttpServletRequest) req;
        if (request.getMethod().equalsIgnoreCase("OPTIONS")) {
            chain.doFilter(req, res);
        } else {

            String workingDir = System.getProperty("user.dir");
            System.out.println("Current working directory : " + workingDir);

            final String authHeader = request.getHeader("Authorization");
            if (authHeader == null || !authHeader.startsWith("Bearer ")) {
                throw new ServletException("Missing or invalid Authorization header.");
            }

            final String token = authHeader.substring(7); // The part after "Bearer "
            try {
                JWSObject jwsObject = JWSObject.parse(token);
                JWSVerifier verifier = new RSASSAVerifier(getPublicKey("szabo.cer"));
                jwsObject.verify(verifier);
            } catch (ParseException e) {
                e.printStackTrace();
            } catch (GeneralSecurityException e) {
                e.printStackTrace();
            } catch (JOSEException e) {
                e.printStackTrace();
            }
            chain.doFilter(req, res);
        }

    }

以下是完整的类代码:

package com.associations.security;

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSObject;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import org.apache.tomcat.util.codec.binary.Base64;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.ParseException;


/**
 * Created by admin on 16.07.2017.
 */
public class JwtFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    private static String getKey(String filename) throws IOException {
        // Read key from file
        String strKeyPEM = "";
        BufferedReader br = new BufferedReader(new FileReader(filename));
        String line;
        while ((line = br.readLine()) != null) {
            strKeyPEM += line + "\n";
        }
        br.close();
        return strKeyPEM;
    }

    public static RSAPublicKey getPublicKey(String filename) throws IOException, GeneralSecurityException {
        String publicKeyPEM = getKey(filename);
        return getPublicKeyFromString(publicKeyPEM);
    }

    public static RSAPublicKey getPublicKeyFromString(String key) throws IOException, GeneralSecurityException {
        String publicKeyPEM = key;
        publicKeyPEM = publicKeyPEM.replace("-----BEGIN PUBLIC KEY-----\n", "");
        publicKeyPEM = publicKeyPEM.replace("-----END PUBLIC KEY-----", "");
        byte[] encoded = Base64.decodeBase64(publicKeyPEM);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(new PKCS8EncodedKeySpec(encoded));
        return pubKey;
    }

    @Override
    public void doFilter(final ServletRequest req,
                         final ServletResponse res,
                         final FilterChain chain) throws IOException, ServletException {


        final HttpServletRequest request = (HttpServletRequest) req;
        if (request.getMethod().equalsIgnoreCase("OPTIONS")) {
            chain.doFilter(req, res);
        } else {

            String workingDir = System.getProperty("user.dir");
            System.out.println("Current working directory : " + workingDir);

            final String authHeader = request.getHeader("Authorization");
            if (authHeader == null || !authHeader.startsWith("Bearer ")) {
                throw new ServletException("Missing or invalid Authorization header.");
            }

            final String token = authHeader.substring(7); // The part after "Bearer "
            try {
                JWSObject jwsObject = JWSObject.parse(token);
                JWSVerifier verifier = new RSASSAVerifier(getPublicKey("szabo.cer"));
                jwsObject.verify(verifier);
            } catch (ParseException e) {
                e.printStackTrace();
            } catch (GeneralSecurityException e) {
                e.printStackTrace();
            } catch (JOSEException e) {
                e.printStackTrace();
            }
            chain.doFilter(req, res);
        }

    }


    public void destroy() {

    }
}

这是堆栈跟踪:

2017-07-21 09:18:39.804  INFO 8852 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2017-07-21 09:18:39.805  INFO 8852 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2017-07-21 09:18:39.822  INFO 8852 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 17 ms
Current working directory : E:\AdrianEmberTests\szabo
java.security.spec.InvalidKeySpecException: Only RSAPublicKeySpec and X509EncodedKeySpec supported for RSA public keys
    at sun.security.rsa.RSAKeyFactory.generatePublic(RSAKeyFactory.java:306)
    at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:201)
    at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
    at com.associations.security.JwtFilter.getPublicKeyFromString(JwtFilter.java:51)
    at com.associations.security.JwtFilter.getPublicKey(JwtFilter.java:42)
    at com.associations.security.JwtFilter.doFilter(JwtFilter.java:77)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

1 个答案:

答案 0 :(得分:1)

您正在使用旨在包装私钥的PKCS8EncodedKeySpec构建公钥

 RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(new PKCS8EncodedKeySpec(encoded));

使用此

RSAPublicKey pubKey = (RSAPublicKey)
     KeyFactory.getInstance("RSA")
           .generatePublic(new X509EncodedKeySpec(bytes));