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

Spring Boot 3.3.0集成Azure AD SAML SSO:证书验证咨询

关于Spring Boot 3.3.0 + Azure AD SAML SSO的证书验证问题

一、确认SAML响应是否使用Azure配置的证书验证

1. 通过日志排查

Spring Security SAML2默认会自动验证SAML响应的签名,开启DEBUG级别日志可以直接查看验证过程及使用的证书信息:
在application.properties中添加日志配置:

logging.level.org.springframework.security.saml2=DEBUG
logging.level.org.opensaml=DEBUG

登录成功后,查看日志会包含类似以下信息:

验证SAML响应签名成功,使用证书指纹: [SHA-256指纹值]
你可以将这个指纹和Azure AD应用中配置的证书指纹对比,确认是否一致。

2. 自定义逻辑获取验证证书

你可以在自定义的customSAMLAuthenticationHandler中,从认证令牌里提取实际用于验证的证书,代码示例如下:

@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
    if (authentication instanceof Saml2AuthenticationToken) {
        Saml2AuthenticationToken samlToken = (Saml2AuthenticationToken) authentication;
        Saml2Response samlResponse = samlToken.getSaml2Response();
        X509Certificate signingCert = samlResponse.getVerificationCertificate();
        
        // 生成证书SHA-256指纹
        String fingerprint = generateSha256Fingerprint(signingCert);
        System.out.println("验证SAML响应的证书指纹: " + fingerprint);
        // 此处可将指纹与Azure配置的证书指纹做对比
    }
    // 后续跳转或业务逻辑处理
}

private String generateSha256Fingerprint(X509Certificate cert) throws NoSuchAlgorithmException {
    MessageDigest md = MessageDigest.getInstance("SHA-256");
    byte[] digest = md.digest(cert.getEncoded());
    StringBuilder sb = new StringBuilder();
    for (byte b : digest) {
        sb.append(String.format("%02x", b)).append(":");
    }
    return sb.deleteCharAt(sb.length() - 1).toString();
}

二、验证Azure AD应用中Base64格式的证书

1. 提取并解析Base64证书

从Azure AD应用的SAML签名证书中复制Base64内容(可保留或去除首尾的-----BEGIN CERTIFICATE-----/-----END CERTIFICATE-----标记),通过以下代码解析为X509证书并验证:

import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.io.ByteArrayInputStream;
import java.util.Base64;
import java.security.MessageDigest;

public class AzureCertValidator {
    public static void main(String[] args) throws Exception {
        // 替换为Azure获取的Base64证书内容
        String azureBase64Cert = "你的Azure Base64证书字符串";
        
        // 清理证书内容中的换行和标记
        String cleanedCert = azureBase64Cert.replaceAll("-----BEGIN CERTIFICATE-----", "")
                                           .replaceAll("-----END CERTIFICATE-----", "")
                                           .replaceAll("\\s+", "");
        
        // 解析为X509证书
        byte[] certBytes = Base64.getDecoder().decode(cleanedCert);
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(certBytes));
        
        // 验证证书有效性
        cert.checkValidity(); // 检查当前时间是否在证书有效期内
        System.out.println("证书有效期起始: " + cert.getNotBefore());
        System.out.println("证书有效期结束: " + cert.getNotAfter());
        System.out.println("证书颁发者: " + cert.getIssuerDN());
        System.out.println("证书SHA-256指纹: " + generateSha256Fingerprint(cert));
    }

    private static String generateSha256Fingerprint(X509Certificate cert) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] digest = md.digest(cert.getEncoded());
        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
            sb.append(String.format("%02x", b)).append(":");
        }
        return sb.deleteCharAt(sb.length() - 1).toString();
    }
}

2. 对比确认

将解析出的Azure证书指纹,和之前从SAML响应中获取的验证证书指纹对比,若一致则说明SAML响应确实使用了你在Azure配置的证书进行验证。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 18:47:02