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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 08:54:55