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

Spring Boot中SOAP请求返回Unauthorized [401]时如何添加用户名密码实现有效请求

Spring Boot解决SOAP请求401 Unauthorized:添加用户名密码的两种方案

刚好之前在项目里踩过这个坑,给你分享两种最常用的解决方式,你可以根据目标SOAP服务的认证要求来选:

一、HTTP Basic 认证(大部分SOAP服务用这个)

很多SOAP服务会用HTTP层面的Basic认证,也就是把用户名密码编码后放在请求头里。这里有两种实现方式:

方式1:用HttpComponentsMessageSender配置(推荐)

这种方式依赖Apache HttpClient,支持更多HTTP特性,配置也更简洁:

首先确保你的pom.xml(或build.gradle)里有这些依赖:

<!-- Spring Web Services 核心依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<!-- Apache HttpClient,用于处理带认证的HTTP请求 -->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>

然后写配置类,把用户名密码注入到WebServiceTemplate中:

@Configuration
public class SoapClientConfig {

    @Value("${soap.service.username}")
    private String username;

    @Value("${soap.service.password}")
    private String password;

    @Value("${soap.service.url}")
    private String soapServiceUrl;

    @Bean
    public WebServiceTemplate webServiceTemplate() {
        WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
        webServiceTemplate.setDefaultUri(soapServiceUrl);
        
        // 配置带Basic认证的HTTP发送器
        HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender();
        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(
                AuthScope.ANY, // 匹配任意主机和端口,也可以指定具体的服务地址
                new UsernamePasswordCredentials(username, password)
        );
        
        CloseableHttpClient httpClient = HttpClientBuilder.create()
                .setDefaultCredentialsProvider(credentialsProvider)
                .build();
        messageSender.setHttpClient(httpClient);
        
        webServiceTemplate.setMessageSender(messageSender);
        
        // 配置JAXB的Marshaller/Unmarshaller,用于序列化和反序列化SOAP消息
        webServiceTemplate.setMarshaller(jaxb2Marshaller());
        webServiceTemplate.setUnmarshaller(jaxb2Marshaller());
        
        return webServiceTemplate;
    }

    @Bean
    public Jaxb2Marshaller jaxb2Marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        // 替换成你自己的SOAP实体类所在的包路径
        marshaller.setContextPath("com.yourproject.soap.model");
        return marshaller;
    }
}

之后你直接注入WebServiceTemplate调用sendAndReceive方法,就会自动带上Basic认证头了。

方式2:自定义拦截器手动添加认证头

如果不想引入HttpClient依赖,也可以写一个拦截器手动构造Authorization头:

public class BasicAuthClientInterceptor implements ClientInterceptor {

    private final String authHeader;

    public BasicAuthClientInterceptor(String username, String password) {
        // 编码用户名密码生成Basic认证头
        String auth = username + ":" + password;
        byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(StandardCharsets.ISO_8859_1));
        this.authHeader = "Basic " + new String(encodedAuth);
    }

    @Override
    public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
        // 获取当前请求的HTTP连接
        TransportContext transportContext = TransportContextHolder.getTransportContext();
        HttpUrlConnection connection = (HttpUrlConnection) transportContext.getConnection();
        
        // 添加Authorization头
        connection.setRequestProperty("Authorization", authHeader);
        return true;
    }

    @Override
    public boolean handleResponse(MessageContext messageContext) throws WebServiceClientException {
        return true;
    }

    @Override
    public boolean handleFault(MessageContext messageContext) throws WebServiceClientException {
        return true;
    }

    @Override
    public void afterCompletion(MessageContext messageContext, Exception ex) throws WebServiceClientException {
        // 不需要额外清理,空实现即可
    }
}

然后在配置WebServiceTemplate的时候添加这个拦截器:

webServiceTemplate.setInterceptors(new ClientInterceptor[]{
        new BasicAuthClientInterceptor(username, password)
});

二、WS-Security UsernameToken 认证(针对要求SOAP头安全的服务)

有些严格的SOAP服务会要求把认证信息放在SOAP消息的Header里,而不是HTTP头。这时候需要用Spring WS的WS-Security支持:

首先添加WS-Security的依赖:

<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-ws-security</artifactId>
</dependency>

然后配置Wss4jSecurityInterceptor:

@Configuration
public class SoapClientConfig {

    @Value("${soap.service.username}")
    private String username;

    @Value("${soap.service.password}")
    private String password;

    @Value("${soap.service.url}")
    private String soapServiceUrl;

    @Bean
    public WebServiceTemplate webServiceTemplate() {
        WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
        webServiceTemplate.setDefaultUri(soapServiceUrl);
        // 添加WS-Security拦截器
        webServiceTemplate.setInterceptors(new ClientInterceptor[]{wss4jSecurityInterceptor()});
        webServiceTemplate.setMarshaller(jaxb2Marshaller());
        webServiceTemplate.setUnmarshaller(jaxb2Marshaller());
        return webServiceTemplate;
    }

    @Bean
    public Wss4jSecurityInterceptor wss4jSecurityInterceptor() {
        Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();
        // 指定要执行的安全动作:添加UsernameToken
        interceptor.setSecurementActions("UsernameToken");
        // 设置认证用户名
        interceptor.setSecurementUsername(username);
        // 设置认证密码
        interceptor.setSecurementPassword(password);
        // 密码类型:PasswordText是明文,PasswordDigest是摘要,根据服务端要求改
        interceptor.setSecurementPasswordType("PasswordText");
        return interceptor;
    }

    @Bean
    public Jaxb2Marshaller jaxb2Marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        marshaller.setContextPath("com.yourproject.soap.model");
        return marshaller;
    }
}

这个配置会在你的SOAP请求Header里自动生成<wsse:UsernameToken>元素,包含用户名和密码,符合WS-Security标准。

最后提醒一下:先搞清楚目标SOAP服务到底用的是哪种认证方式——可以看服务的文档,或者抓包看正常请求的结构,再选对应的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 08:22:35