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

Apache CXF如何为不同SOAP操作指定加密与签名规则

Apache CXF 按SOAP操作差异化配置WSS4J安全规则方案

以下是两种可直接落地的配置方案,无需修改原有WSS4J加解密、签名逻辑:

方案1:自定义路由拦截器(灵活度最高,适合操作数量多、规则可能动态调整的场景)

核心逻辑是先注册一个高优先级的路由拦截器,解析当前请求的SOAP操作名后,动态给需要安全校验的请求绑定WSS4J拦截器。

  • 实现自定义路由拦截器:
public class WsSecurityRouteInterceptor extends AbstractPhaseInterceptor<Message> {
    // 配置需要加密签名的操作本地名集合,可替换为从配置文件读取
    private static final Set<String> SECURE_REQUIRED_OPS = Set.of("createOrder", "payOrder", "querySensitiveInfo");
    // 预初始化带安全规则的WSS4J拦截器
    private final WSS4JStaxInInterceptor secureInInterceptor;
    private final WSS4JStaxOutInterceptor secureOutInterceptor;

    public WsSecurityRouteInterceptor() {
        // 配置为RECEIVE阶段执行,早于WSS4J默认的执行阶段
        super(Phase.RECEIVE);
        // 入站WSS4J配置,和你之前的全局配置逻辑完全一致
        Map<String, Object> inProps = new HashMap<>();
        inProps.put(ConfigurationConstants.ACTION, "UsernameToken Signature Encrypt");
        inProps.put(ConfigurationConstants.SIG_VER_PROP_FILE, "publicKey.properties");
        inProps.put(ConfigurationConstants.DEC_PROP_FILE, "privateKey.properties");
        secureInInterceptor = new WSS4JStaxInInterceptor(inProps);
        
        // 出站WSS4J配置,按需配置响应加密、签名规则
        Map<String, Object> outProps = new HashMap<>();
        outProps.put(ConfigurationConstants.ACTION, "Signature Encrypt");
        outProps.put(ConfigurationConstants.SIG_PROP_FILE, "privateKey.properties");
        outProps.put(ConfigurationConstants.ENC_PROP_FILE, "publicKey.properties");
        secureOutInterceptor = new WSS4JStaxOutInterceptor(outProps);
    }

    @Override
    public void handleMessage(Message message) throws Fault {
        BindingOperationInfo operationInfo = message.getExchange().getBindingOperationInfo();
        if (operationInfo == null) {
            return;
        }
        String opName = operationInfo.getName().getLocalPart();
        // 只有指定操作才加载WSS4J安全拦截器
        if (SECURE_REQUIRED_OPS.contains(opName)) {
            message.getInterceptorChain().add(secureInInterceptor);
            message.getExchange().getOutMessage().getInterceptorChain().add(secureOutInterceptor);
        }
    }
}
  • 把自定义路由拦截器注册到服务端点:
EndpointImpl endpoint = (EndpointImpl) Endpoint.publish("你的服务地址", new 你的服务实现类());
endpoint.getInInterceptors().add(new WsSecurityRouteInterceptor());

注意不要同时配置全局的WSS4JStaxIn/OutInterceptor,否则所有请求都会默认走安全校验,差异化规则会失效

方案2:操作级绑定拦截器(适合操作数量少、规则固定的场景)

直接给需要安全校验的操作单独绑定WSS4J拦截器,无需额外写路由逻辑:

EndpointImpl endpoint = (EndpointImpl) Endpoint.publish("你的服务地址", new 你的服务实现类());
// 初始化WSS4J入站、出站拦截器,逻辑和方案1一致
WSS4JStaxInInterceptor secureIn = buildSecureInInterceptor();
WSS4JStaxOutInterceptor secureOut = buildSecureOutInterceptor();

// 遍历所有服务操作,给需要安全校验的操作绑定拦截器
for (BindingOperationInfo op : endpoint.getBinding().getBindingInfo().getOperations()) {
    if (Set.of("createOrder", "payOrder").contains(op.getName().getLocalPart())) {
        op.getInInterceptors().add(secureIn);
        op.getOutInterceptors().add(secureOut);
    }
}

额外注意事项

  • 如果存在相同本地名、不同命名空间的SOAP操作,匹配时需要加上operationInfo.getName().getNamespaceURI()的判断,避免误匹配
  • 如果你用Spring XML配置CXF端点,可以自定义BeanPostProcessor在端点初始化完成后执行上述操作绑定逻辑,和Java代码逻辑完全一致

内容的提问来源于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:48:00