You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中如何通过证书指纹验证跨服务JWT令牌签名?

用S1证书指纹验证JWT签名的Java实现方案

核心思路是:先通过S1的证书指纹确认拿到的是合法的S1证书,再从证书中提取公钥,最后用公钥验证JWT的签名。以下是具体步骤和代码示例:

步骤1:预先存储S1的证书指纹

S2要提前保存好S1公开的证书指纹(通常是SHA-256格式,比如AA:BB:CC:DD...这种带冒号的十六进制形式),用来后续校验证书的合法性。

步骤2:获取S1证书并校验指纹

从可信渠道获取S1的证书文件(比如预先部署在S2本地,或通过安全方式拉取),然后计算该证书的指纹,和存储的S1指纹对比,确认证书未被篡改。

计算证书指纹的代码示例:

import java.io.FileInputStream;
import java.security.MessageDigest;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

public static String calculateCertFingerprint(String certFilePath) throws Exception {
    CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
    try (FileInputStream fis = new FileInputStream(certFilePath)) {
        X509Certificate cert = (X509Certificate) certFactory.generateCertificate(fis);
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] fingerprintBytes = md.digest(cert.getEncoded());
        
        // 转成标准的带冒号十六进制格式
        StringBuilder sb = new StringBuilder();
        for (byte b : fingerprintBytes) {
            sb.append(String.format("%02X:", b));
        }
        return sb.deleteCharAt(sb.length() - 1).toString();
    }
}

调用该方法后,将返回的指纹与预先存储的S1指纹对比,一致则说明证书是合法的S1证书。

步骤3:从合法证书中提取公钥

确认证书合法后,提取用于验证签名的公钥:

import java.io.FileInputStream;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

public static PublicKey getPublicKeyFromCert(String certFilePath) throws Exception {
    CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
    try (FileInputStream fis = new FileInputStream(certFilePath)) {
        X509Certificate cert = (X509Certificate) certFactory.generateCertificate(fis);
        return cert.getPublicKey();
    }
}

步骤4:用公钥验证JWT签名

这里提供两种常用JWT库的实现:

方式1:使用JJWT库

先添加Maven依赖:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>

验证代码:

import io.jsonwebtoken.Jwts;

public static boolean validateJwtSignature(String jwtToken, PublicKey publicKey) {
    try {
        Jwts.parserBuilder()
                .setSigningKey(publicKey)
                .build()
                .parseClaimsJws(jwtToken);
        return true;
    } catch (Exception e) {
        // 签名无效、令牌过期、格式错误等异常都会触发返回false
        return false;
    }
}

方式2:使用Nimbus JOSE + JWT库

添加Maven依赖:

<dependency>
    <groupId>com.nimbusds</groupId>
    <artifactId>nimbus-jose-jwt</artifactId>
    <version>9.37.3</version>
</dependency>

验证代码:

import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jwt.SignedJWT;

public static boolean validateJwtSignature(String jwtToken, PublicKey publicKey) throws Exception {
    SignedJWT signedJWT = SignedJWT.parse(jwtToken);
    JWSVerifier verifier = new RSASSAVerifier((java.security.interfaces.RSAPublicKey) publicKey);
    return signedJWT.verify(verifier);
}

关键注意事项

  • 务必确保S1的证书指纹是公开且可信的,避免中间人替换证书
  • 验证签名的同时,建议额外校验JWT的过期时间、issuer等声明,确保令牌的完整性和有效性
  • 如果S1更新证书,要同步更新S2存储的指纹,避免出现验证失败的情况

内容的提问来源于stack exchange,提问作者meg1311

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 09:43:28