【问题标题】:It is possible to use java with jwt and rs256 and auth0? [closed]可以将 java 与 jwt 和 rs256 以及 auth0 一起使用吗? [关闭]
【发布时间】:2017-07-22 04:05:06
【问题描述】:

这是我在尝试验证 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)

【问题讨论】:

  • 您的代码不存在。贴出getPublicKey的代码和full.stack trace
  • 不要发布代码或跟踪作为答案。只需编辑您自己的帖子。我为你做的
  • 在尝试提出更多问题之前,请阅读How do I ask a good question?

标签: java spring-boot jwt


【解决方案1】:

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

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

使用这个

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

【讨论】:

  • 嗨,使用您的代码后,我得到:java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: DerInputStream.getLength(): lengthTag=111,太大。在 sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:205),但它有助于更​​好地理解问题。所以我发现它现在似乎工作正常。 connect2id.com/products/nimbus-jose-jwt/examples/…
  • 是否以有效的 PEM 格式对您的 RSA 密钥进行了编码? X509EncodedKeySpec 期望包含算法和密钥内容的 ASN.1 结构的 DER 编码,似乎不正确。您链接的示例从 Json 网络密钥格式(JWK)中读取它
  • 在 Auth0 上,如果您转到客户端 -> 设置 -> 高级设置 -> 证书,它们会为您提供下载证书的链接,您可以选择 pem、cer 或 PKCS#7。更多的,我说不出来。我使用 express js,它提供了一个简单的模块,它知道正确读取该 pem 文件。我在 Spring Boot 中为此花了很多时间,但似乎他们不喜欢 auth0。
  • 无论如何,我找到的解决方案似乎完全符合我的要求,但它向 auth0 发出请求以获取该公钥。
猜你喜欢
  • 2017-09-28
  • 2021-03-14
  • 2015-03-20
  • 1970-01-01
  • 2019-04-28
  • 1970-01-01
  • 1970-01-01
  • 2010-09-10
  • 2022-06-15
相关资源
最近更新 更多