Spring Boot 3 – 使用RSA256公钥验证JWT令牌

huangapple go评论63阅读模式
英文:

Spring Boot 3 - Validate JWT token using RSA256 public key

问题

使用新的 Spring-Security-Web,从6.0.0开始,我想知道如何使用RS256公钥验证Bearer JWT,并在Spring Security Servlet上下文中设置"Authentication"。

目前,我已经编写了一个自定义的JwtTokenFilter,将其添加到SecurityFilterChain中。它使用X509EncodedKeySpec读取公钥。

jwtPublicKey指向.pub文件

Resource resource = new ClassPathResource(jwtPublicKey);
FileInputStream is = new FileInputStream(resource.getFile());
byte[] bytes = is.readAllBytes();
is close();

String temp = new String(bytes);
String publicKeyPEM = temp.replace("-----BEGIN PUBLIC KEY-----", "");
publicKeyPEM = publicKeyPEM.replace("-----END PUBLIC KEY-----", "");
publicKeyPEM = publicKeyPEM.replace("\n", "");

// 解码文件内容的Base64
base64EncodedKeyBytes = java.util.Base64.getDecoder().decode(publicKeyPEM);

// 将文件内容转换为RSAPublicKey对象
X509EncodedKeySpec spec = new X509EncodedKeySpec(base64EncodedKeyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
publicKey = (RSAPublicKey) kf.generatePublic(spec);

*base64EncodedKeyBytespublicKey 是静态变量。

现在我如何使用这个公钥验证JWT?
我觉得这一切都非常繁琐,我有一种感觉,Spring中一定已经包含了更简便的方法?(天啊,请!)

英文:

Using the new Spring-Security-Web starting with 6.0.0, I wanted to know how to validate a Bearer JWT using a RS256 public key and set the "Authentication" in the Spring Security Servlet Context.

Currently I've written a custom JwtTokenFilter which is added to a SecurityFilterChain. It reads the public key using the X509EncodedKeySpec

jwtPublicKey points to the .pub file

Resource resource = new ClassPathResource(jwtPublicKey);
FileInputStream is = new FileInputStream(resource.getFile());
byte[] bytes = is.readAllBytes();
is.close();

String temp = new String(bytes);
String publicKeyPEM = temp.replace("-----BEGIN PUBLIC KEY-----", "");
publicKeyPEM = publicKeyPEM.replace("-----END PUBLIC KEY-----", "");
publicKeyPEM = publicKeyPEM.replace("\n", "");

// Decode the contents of the file from Base64
base64EncodedKeyBytes = java.util.Base64.getDecoder().decode(publicKeyPEM);

// Convert the contents of the file to a RSAPublicKey object
X509EncodedKeySpec spec = new X509EncodedKeySpec(base64EncodedKeyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
publicKey = (RSAPublicKey) kf.generatePublic(spec);

*base64EncodedKeyBytes and publicKey are static variables.

How can I now validate a JWT using this public key?
I feel like this is all very tedious and I have the feeling there must be a shorter way already included into Spring? (oh lord, please!)

答案1

得分: 1

以下是代码的翻译部分:

首先,您可以像这样尝试:

首先,在您的 pom.xml 文件中添加 java-jwt 依赖项:

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>4.0.0</version>
</dependency>

接下来,您可以按照以下方式修改您的逻辑:

@Component
public class JwtTokenVerifier {
 
    // 请在此处输入您的 JWT 令牌和公钥
    public static final String jwtToken = "";
    public static final String publicKey = "";
 
    public boolean isTokenValid(String token) {
        try {
            buildJWTVerifier().verify(token.replace("Bearer ", ""));
            // 如果令牌有效,将不会抛出异常
            return true;
        } catch (CertificateException e) {
            // 如果来自 buildJWTVerifier() 的 CertificateException
            e.printStackTrace();
            return false;
        } catch (JWTVerificationException e) {
            // 如果 JWT 令牌无效
            e.printStackTrace();
            return false;
        } catch (Exception e) {
            // 如果出现其他异常
            e.printStackTrace();
            return false;
        }
    }
 
 
    private JWTVerifier buildJWTVerifier() throws CertificateException {
        var algo = Algorithm.RSA256(getRSAPublicKey(), null);
        return JWT.require(algo).build();
    }
 
    private RSAPublicKey getRSAPublicKey() throws CertificateException {
        var decode = Base64.getDecoder().decode(publicKey);
        var certificate = CertificateFactory.getInstance("X.509")
                .generateCertificate(new ByteArrayInputStream(decode));
        var publicKey = (RSAPublicKey) certificate.getPublicKey();
        return publicKey;
    }
}
英文:

You can try something like this:

First, you can add the java-jwt dependency in your pom.xml file

&lt;dependency&gt;
&lt;groupId&gt;com.auth0&lt;/groupId&gt;
&lt;artifactId&gt;java-jwt&lt;/artifactId&gt;
&lt;version&gt;4.0.0&lt;/version&gt;
&lt;/dependency&gt;

Next, you can modify your logic as follows:

@Component
public class JwtTokenVerifier {
// please input your jwt token &amp; public key here
public static final String jwtToken = &quot;&quot;;
public static final String publicKey = &quot;&quot;;
public boolean isTokenValid(String token) {
try {
buildJWTVerifier().verify(token.replace(&quot;Bearer &quot;, &quot;&quot;));
// if token is valid no exception will be thrown
return true;
} catch (CertificateException e) {
//if CertificateException comes from buildJWTVerifier()
e.printStackTrace();
return false;
} catch (JWTVerificationException e) {
// if JWT Token in invalid
e.printStackTrace();
return false;
} catch (Exception e) {
// If any other exception comes
e.printStackTrace();
return false;
}
}
private JWTVerifier buildJWTVerifier() throws CertificateException {
var algo = Algorithm.RSA256(getRSAPublicKey(), null);
return JWT.require(algo).build();
}
private RSAPublicKey getRSAPublicKey() throws CertificateException {
var decode = Base64.getDecoder().decode(publicKey);
var certificate = CertificateFactory.getInstance(&quot;X.509&quot;)
.generateCertificate(new ByteArrayInputStream(decode));
var publicKey = (RSAPublicKey) certificate.getPublicKey();
return publicKey;
}
}

huangapple
  • 本文由 发表于 2023年3月31日 20:45:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/75898689.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定