如何在WebServiceTemplate的SOAP调用中集成spring.security.oauth2.client
为WebServiceTemplate添加Keycloak认证令牌
1. 配置OAuth2客户端获取令牌
先在Spring Boot中配置Keycloak作为OAuth2客户端,借助Spring Security OAuth2 Client的自动配置来管理令牌的获取与刷新。
在application.yml中添加配置:
spring: security: oauth2: client: registration: keycloak-soap: client-id: 你的客户端ID client-secret: 你的客户端密钥 authorization-grant-type: client_credentials scope: openid, soap-api-access provider: keycloak-soap: token-uri: https://你的Keycloak域名/auth/realms/你的领域/protocol/openid-connect/token
2. 实现令牌获取服务
用Spring Security提供的OAuth2AuthorizedClientManager来获取有效访问令牌,它会自动处理令牌缓存和过期刷新:
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; import org.springframework.security.oauth2.client.request.OAuth2AuthorizeRequest; import org.springframework.stereotype.Service; @Service public class KeycloakTokenService { private final OAuth2AuthorizedClientManager authorizedClientManager; public KeycloakTokenService(OAuth2AuthorizedClientManager authorizedClientManager) { this.authorizedClientManager = authorizedClientManager; } public String getAccessToken() { OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("keycloak-soap") .principal("soap-client") .build(); OAuth2AuthorizedClient authorizedClient = authorizedClientManager.authorize(authorizeRequest); return authorizedClient.getAccessToken().getTokenValue(); } }
3. 自定义WebServiceMessageCallback添加认证头
创建自定义的WebServiceMessageCallback,在请求发送前注入Authorization头:
import org.springframework.ws.client.core.WebServiceMessageCallback; import org.springframework.ws.soap.SoapMessage; import javax.xml.transform.TransformerException; import java.io.IOException; public class SoapAuthHeaderCallback implements WebServiceMessageCallback { private final String accessToken; public SoapAuthHeaderCallback(String accessToken) { this.accessToken = accessToken; } @Override public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException { if (message instanceof SoapMessage soapMessage) { soapMessage.getSoapHeader().addHeaderElement(javax.xml.namespace.QName.valueOf("Authorization")) .setText("Bearer " + accessToken); } } }
4. 在WebServiceTemplate调用中应用认证
注入KeycloakTokenService和WebServiceTemplate,调用SOAP接口时传入自定义的Callback:
import org.springframework.stereotype.Service; import org.springframework.ws.client.core.WebServiceTemplate; @Service public class SoapClientService { private final WebServiceTemplate webServiceTemplate; private final KeycloakTokenService tokenService; public SoapClientService(WebServiceTemplate webServiceTemplate, KeycloakTokenService tokenService) { this.webServiceTemplate = webServiceTemplate; this.tokenService = tokenService; } public Object callSoapService(Object requestPayload) { String accessToken = tokenService.getAccessToken(); return webServiceTemplate.marshalSendAndReceive( "https://外部SOAP服务地址", requestPayload, new SoapAuthHeaderCallback(accessToken) ); } }
关键注意事项
- 如果使用用户授权模式(authorization_code),需替换
authorization-grant-type并处理当前登录用户的上下文,此时principal要传入用户相关信息。 OAuth2AuthorizedClientManager会自动缓存令牌,避免重复请求Keycloak,令牌过期时会自动触发刷新。- 确保Keycloak客户端配置的
scope包含外部SOAP服务要求的权限。
内容的提问来源于stack exchange,提问作者Eljah
相关产品推荐
相关产品推荐

