Spring Boot 3与Spring WS Security:SOAP安全头外部REST验证问询
Spring Boot 3.2.3对接外部REST验证SOAP安全头用户名密码
你可以通过自定义Spring Security的AuthenticationProvider和复用现有Spring WS安全组件来实现需求,具体步骤如下:
1. 自定义外部REST验证的AuthenticationProvider
这个类负责提取SOAP头中的用户名密码,调用外部REST接口完成验证:
@Component public class ExternalRestAuthenticationProvider implements AuthenticationProvider { private final RestTemplate restTemplate; public ExternalRestAuthenticationProvider(RestTemplate restTemplate) { this.restTemplate = restTemplate; } @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String username = authentication.getName(); String password = authentication.getCredentials().toString(); // 调用外部REST验证接口,替换为你的实际端点 Boolean isValid = restTemplate.postForObject( "https://your-external-auth.com/api/validate-credentials", new AuthRequest(username, password), Boolean.class ); if (Boolean.TRUE.equals(isValid)) { // 验证通过,构造已认证的用户对象 UserDetails authenticatedUser = User.withUsername(username) .password("") // 本地无需存储密码,仅用于框架兼容 .authorities("ROLE_SOAP_USER") .build(); return new UsernamePasswordAuthenticationToken( authenticatedUser, password, authenticatedUser.getAuthorities() ); } else { throw new BadCredentialsException("Invalid username or password from external system"); } } @Override public boolean supports(Class<?> authentication) { // 适配SOAP安全头解析后的UsernamePasswordAuthenticationToken类型 return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication); } // 封装请求体的内部类 private static class AuthRequest { private String username; private String password; public AuthRequest(String username, String password) { this.username = username; this.password = password; } // Getters & Setters public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } }
2. 配置Spring Security加载自定义验证器
注册自定义的AuthenticationProvider,让Spring Security使用它处理认证请求:
@Configuration @EnableWebSecurity public class SecurityConfig { private final ExternalRestAuthenticationProvider externalAuthProvider; public SecurityConfig(ExternalRestAuthenticationProvider externalAuthProvider) { this.externalAuthProvider = externalAuthProvider; } @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception { return authConfig.getAuthenticationManager(); } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .authenticationProvider(externalAuthProvider); return http.build(); } // 配置RestTemplate用于调用外部接口 @Bean public RestTemplate restTemplate() { return new RestTemplate(); } }
3. 配置Spring WS安全,复用现有验证逻辑
保持你已有的nonce和时间戳验证配置,同时关联Spring Security的认证管理器:
@Configuration public class WsSecurityConfig extends WsConfigurerAdapter { private final AuthenticationManager authenticationManager; public WsSecurityConfig(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } @Override public void configureWsSecurity(WsSecurityConfigurer wsSecurity) throws Exception { wsSecurity .authenticationManager(authenticationManager) .wsSecurityInterceptor(wsSecurityInterceptor()); } @Bean public WsSecurityInterceptor wsSecurityInterceptor() { WsSecurityInterceptor interceptor = new WsSecurityInterceptor(); // 保留你已配置的nonce、时间戳验证规则,比如: interceptor.setValidationActions("UsernameToken"); interceptor.setValidationCallbackHandler(validationCallbackHandler()); return interceptor; } @Bean public CallbackHandler validationCallbackHandler() { SpringSecurityPasswordValidationCallbackHandler callbackHandler = new SpringSecurityPasswordValidationCallbackHandler(); callbackHandler.setAuthenticationManager(authenticationManager); return callbackHandler; } }
关键说明
- 复用现有WS安全逻辑:通过
WsSecurityInterceptor的validationActions和validationCallbackHandler,保留原有的nonce、时间戳验证流程,无需改动这部分代码。 - 自动提取用户名密码:Spring WS会自动解析SOAP安全头中的
UsernameToken,封装成UsernamePasswordAuthenticationToken,交给Spring Security的AuthenticationManager处理。 - 无本地密码存储:所有验证逻辑委托给外部REST接口,本地仅负责传递参数和接收验证结果,不需要保存任何用户密码或密钥。
注意事项
- 确保外部REST接口使用HTTPS传输,避免密码明文泄露。
- 可以给
RestTemplate添加超时、重试配置,提升外部调用的可靠性。 - 如果外部接口返回用户权限信息,可以在构造
UserDetails时设置对应的权限,用于后续接口的授权控制。
内容的提问来源于stack exchange,提问作者R Singh
相关产品推荐
相关产品推荐

