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

如何在Spring Boot中结合生成的客户端Stub使用WS-Security

在Spring Boot中为生成的SOAP客户端Stub配置WS-Security(无需修改生成代码)

1. 选择Maven插件生成客户端Stub

推荐用Apache CXF的cxf-codegen-plugin,它生成的Stub能和Spring无缝集成,且支持配置拦截器。示例Maven配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-codegen-plugin</artifactId>
            <version>3.6.2</version>
            <executions>
                <execution>
                    <id>generate-sources</id>
                    <phase>generate-sources</phase>
                    <configuration>
                        <wsdlOptions>
                            <wsdlOption>
                                <wsdl>${project.basedir}/src/main/resources/wsdl/YourService.wsdl</wsdl>
                                <extraargs>
                                    <extraarg>-p</extraarg>
                                    <extraarg>com.yourpackage.client</extraarg>
                                    <extraarg>-client</extraarg>
                                </extraargs>
                            </wsdlOption>
                        </wsdlOptions>
                    </configuration>
                    <goals>
                        <goal>wsdl2java</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

该配置会从指定WSDL生成客户端接口和实现类,存到com.yourpackage.client包下,全程不用手动修改生成代码。

2. 配置WS-Security签名拦截器

创建Spring配置类,定义Wss4jSecurityInterceptor Bean,所有签名参数都可通过配置文件驱动:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor;

@Configuration
public class WsSecurityConfig {

    @Value("${ws.security.key-alias}")
    private String keyAlias;
    @Value("${ws.security.keystore-password}")
    private String keystorePassword;
    @Value("${ws.security.key-password}")
    private String keyPassword;
    @Value("${ws.security.keystore-location}")
    private String keystoreLocation;

    @Bean
    public Wss4jSecurityInterceptor securityInterceptor() {
        Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();
        
        // 指定安全动作:添加XML签名
        interceptor.setSecurementActions("Signature");
        // 密钥库相关配置
        interceptor.setSecurementUsername(keyAlias);
        interceptor.setSecurementPassword(keystorePassword);
        interceptor.setSecurementKeyPassword(keyPassword);
        interceptor.setSecurementKeystoreLocation(keystoreLocation);
        interceptor.setSecurementKeystorePassword(keystorePassword);
        // 指定要签名的SOAP元素(这里对Body签名)
        interceptor.setSecurementSignatureParts("{}{http://schemas.xmlsoap.org/soap/envelope/}Body");
        
        return interceptor;
    }
}

对应的application.properties配置:

ws.security.key-alias=your-key-alias
ws.security.keystore-password=your-keystore-pass
ws.security.key-password=your-key-pass
ws.security.keystore-location=classpath:keystore.jks

3. 将拦截器绑定到生成的客户端Stub

通过CXF的JaxWsProxyFactoryBean创建客户端实例,并把拦截器加入其输出拦截器链,完全不用修改生成的Stub代码:

import com.yourpackage.client.YourServicePortType;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SoapClientConfig {

    private final Wss4jSecurityInterceptor securityInterceptor;

    public SoapClientConfig(Wss4jSecurityInterceptor securityInterceptor) {
        this.securityInterceptor = securityInterceptor;
    }

    @Bean
    public YourServicePortType yourServiceClient() {
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        // 指定生成的客户端接口
        factory.setServiceClass(YourServicePortType.class);
        // 设置服务端点地址
        factory.setAddress("http://your-service-endpoint-url");
        
        // 注入WS-Security拦截器
        factory.getOutInterceptors().add(securityInterceptor);
        
        return (YourServicePortType) factory.create();
    }
}

4. 调用测试

在业务代码中直接注入客户端并调用,请求会自动带上签名后的WS-Security头:

import com.yourpackage.client.YourServicePortType;
import org.springframework.stereotype.Service;

@Service
public class BusinessService {

    private final YourServicePortType soapClient;

    public BusinessService(YourServicePortType soapClient) {
        this.soapClient = soapClient;
    }

    public void invokeSoapService() {
        // 直接调用生成的客户端方法,签名逻辑由拦截器自动处理
        soapClient.yourServiceMethod();
    }
}

你可以通过抓包工具(如Wireshark)或开启CXF日志,验证SOAP请求中是否已正确添加带签名的WS-Security头。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 02:00:12