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

Spring WS是否有等效Apache CXF的useReqSigCert配置以用请求证书加密响应

实现方案说明

Spring WS 没有提供与Apache CXF useReqSigCert 完全对应的开箱即用配置项,但可以通过自定义WSS4J安全拦截器的方式实现完全相同的能力:从请求的WS-Security头中提取签名所用的X509证书,再用该证书加密响应的SOAP Body。

核心实现步骤

  • 自定义WSS4J安全拦截器,在请求校验阶段提取请求签名携带的BinarySecurityToken(即X509证书),通过ThreadLocal存储避免线程安全问题
  • 覆写响应加密逻辑,将提取到的证书作为加密公钥注入加密流程,无需从本地密钥库查询对应证书
  • 配置自定义拦截器到Spring WS上下文,启用对应的请求校验和响应加密规则

代码示例

自定义安全拦截器

import org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor;
import org.apache.wss4j.core.WSHandlerResult;
import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
import org.apache.wss4j.common.ext.WSConstants;
import org.springframework.ws.context.MessageContext;
import java.security.cert.X509Certificate;

public class ReqSigCertBasedEncryptInterceptor extends Wss4jSecurityInterceptor {
    // 存储当前请求对应的签名证书,线程隔离
    private final ThreadLocal<X509Certificate> requestSignatureCertHolder = new ThreadLocal<>();

    @Override
    protected void validateRequest(MessageContext messageContext, Object endpoint) throws Exception {
        super.validateRequest(messageContext, endpoint);
        // 从WSS4J请求处理结果中提取签名证书
        WSHandlerResult recvResult = (WSHandlerResult) messageContext.getProperty(WSHandlerConstants.RECV_RESULTS);
        if (recvResult == null) return;
        
        for (WSSecurityEngineResult securityResult : recvResult.getResults()) {
            Integer actionType = (Integer) securityResult.get(WSSecurityEngineResult.TAG_ACTION);
            if (WSConstants.SIGN == actionType) {
                X509Certificate sigCert = (X509Certificate) securityResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
                if (sigCert != null) {
                    requestSignatureCertHolder.set(sigCert);
                    break;
                }
            }
        }
    }

    @Override
    protected void secureResponse(MessageContext messageContext, Object endpoint) throws Exception {
        X509Certificate sigCert = requestSignatureCertHolder.get();
        if (sigCert != null) {
            // 直接使用提取到的证书作为加密公钥
            setEncryptionUser(sigCert.getSubjectX500Principal().getName());
            setKeyStoreCallbackHandler(callbacks -> {
                for (Callback cb : callbacks) {
                    if (cb instanceof KeyStoreCallback keyStoreCb) {
                        keyStoreCb.setCertificate(sigCert);
                    }
                }
            });
        }
        try {
            super.secureResponse(messageContext, endpoint);
        } finally {
            // 必须清理ThreadLocal,避免线程复用导致的数据混乱
            requestSignatureCertHolder.remove();
        }
    }
}

拦截器配置(JavaConfig方式)

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class WsSecurityConfig {
    @Bean
    public ReqSigCertBasedEncryptInterceptor wss4jSecurityInterceptor() {
        ReqSigCertBasedEncryptInterceptor interceptor = new ReqSigCertBasedEncryptInterceptor();
        // 配置请求校验规则:验签 + 解密
        interceptor.setValidationActions("Signature Encrypt");
        interceptor.setValidationSignatureCrypto(yourSignatureVerificationCrypto);
        interceptor.setValidationDecryptionCrypto(yourRequestDecryptionCrypto);
        
        // 配置响应加密规则:仅加密SOAP Body内容
        interceptor.setSecurementActions("Encrypt");
        interceptor.setSecurementEncryptionParts("{Content}{http://schemas.xmlsoap.org/soap/envelope/}Body");
        interceptor.setSecurementEncryptionCrypto(yourResponseEncryptionCrypto);
        return interceptor;
    }
}

注:上述代码中的yourSignatureVerificationCrypto、yourRequestDecryptionCrypto、yourResponseEncryptionCrypto需要替换为你业务中实际配置的WSS4J Crypto实例。

注意事项

  • 请确保请求的WS-Security头中确实携带了明文的BinarySecurityToken,否则会出现证书提取失败的问题,可根据业务需要增加对应的空判断和异常处理逻辑
  • 若对安全等级要求较高,可在提取到证书后增加证书信任校验逻辑,确认证书在你的信任域范围内后再用于加密响应

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 07:24:03