Spring Security 和自定义 ws 身份验证

Posted

技术标签:

【中文标题】Spring Security 和自定义 ws 身份验证【英文标题】:Spring Security and custom ws authentication 【发布时间】:2016-09-05 00:10:27 【问题描述】:

我们刚刚在一个新项目中使用了 Spring Boot 和 Spring Security。问题是,我们公司使用 CXF 和自定义实施的 SAML 身份验证机制。当然,自定义实现相当陈旧,所以我们被锁定到 CXF 2.7.*。

不久前,一切都很好,因为我们只公开了 SOAP Web 服务并且没有使用 Spring Security。我们在旧解决方案中使用的身份验证器使用某种 JBossWebRealm 东西通过 org.apache.catlina.connector.Request 进行身份验证。

但是现在,我们也将公开 REST 服务,使用 LDAP 作为身份验证提供程序。使用 Spring Security 就像做梦一样,但是现在 SOAP 服务的安全性失败了。它现在尝试使用 Spring Security 使用 SAML 令牌作为 AD 的密码进行身份验证。

目前我们有 Spring Boot 创建的默认 Servlet。这个公开了 REST 资源和一个简单的健康检查网页。 然后我们有一个公开 SOAP Web 服务的 servlet 和一个公开指标 (REST) 的 servlet。

Servlet 设置:

@Configuration
@EnableAutoConfiguration
@Import(ApplicationConfig.class)
public class ApplicationServletInitializer extends SpringBootServletInitializer 

    @Bean
    public WebMvcConfigurerAdapter dispatcherServletConfigurer(final MDCInterceptor mdcInterceptor) 
        return new WebMvcConfigurerAdapter() 
            @Override
            public void addResourceHandlers(ResourceHandlerRegistry registry) 
                registry.addResourceHandler("/internal/*");
            

            @Override
            public void addInterceptors(InterceptorRegistry registry) 
                registry.addInterceptor(mdcInterceptor);
            
        ;
    

    @Bean(name = "webServiceServlet")
    public ServletRegistrationBean webServiceServlet() 
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
        servletRegistrationBean.setServlet(new CXFServlet());
        servletRegistrationBean.setName("webServiceServlet");
        servletRegistrationBean.addUrlMappings("/ws/*");
        servletRegistrationBean.setLoadOnStartup(2);
        return servletRegistrationBean;
    

    @Bean(name = "metricsServlet")
    public ServletRegistrationBean metricsServlet() 
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
        servletRegistrationBean.setServlet(new MetricsServlet());
        servletRegistrationBean.setName("metricsServlet");
        servletRegistrationBean.addUrlMappings("/internal/metrics/*");
        servletRegistrationBean.setLoadOnStartup(3);
        return servletRegistrationBean;
    

安全设置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@ComponentScan(basePackageClasses = 
        MDCInterceptor.class,
        WebSecurityConfigurerAdapterConfig.class
)
public class RestSecurityConfig 

    @Value("$ldap.url")
    private String ldapUrl;

    @Value("$ldap.domain")
    private String ldapDomain;

    @Bean
    public ActiveDirectoryLdapAuthenticationProvider authenticationProvider() 
        ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(ldapDomain, ldapUrl);
        provider.setAuthoritiesMapper(authoritiesMapper());
        provider.setUserDetailsContextMapper(userDetailsMapper());
        provider.setUseAuthenticationRequestCredentials(true);
        provider.setConvertSubErrorCodesToExceptions(true);
        return provider;
    

    @Bean
    public MyAuthoritiesMapper authoritiesMapper() 
        return new MyAuthoritiesMapper();
    

    @Bean
    public MyUserDetailsMapper userDetailsMapper() 
        return new MyUserDetailsMapper();
    




@Component
public class WebSecurityConfigurerAdapterConfig extends WebSecurityConfigurerAdapter 

   @Autowired
    private ActiveDirectoryLdapAuthenticationProvider authenticationProvider;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.authenticationProvider(authenticationProvider);
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http.csrf().disable();
            http.authorizeRequests()
                    .antMatchers(HttpMethod.OPTIONS, "/api/**").permitAll()
                    .antMatchers("/api/**").hasRole("READ")
                    .and().httpBasic()
                    .and().anonymous()
                    .principal(anonymousPrincipal())
                    .authorities(anonymousRoles());
    

web.xml 设置:

<security-constraint>
    <web-resource-collection>
        <web-resource-name>All pages</web-resource-name>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
</security-constraint>

有谁知道是否可以解决这个问题?移除对 SOAP Web 服务的 SAML 进行身份验证的旧安全框架的使用不是一种选择。

【问题讨论】:

【参考方案1】:

想通了。 在配置 Spring Security 时,在 WebSecurityConfigurerAdapter 中,也可以覆盖:

protected void configure(WebSecurity web).

在这一项中,您可以指定要忽略的内容。 例如:

web.ignoring().antMatchers("/ws/**");

【讨论】:

以上是关于Spring Security 和自定义 ws 身份验证的主要内容,如果未能解决你的问题,请参考以下文章

spring boot spring security 基于自定义令牌的身份验证和自定义授权

Spring Security 和自定义外部身份验证

带有 LDAP 和自定义 UserDetailsContextMapper 的 Spring Security

Spring Security 自定义 UserDetailsS​​ervice 和自定义 User 类

如何将对象类和自定义属性添加到 LDIF 文件?

Spring-WS WS-Security LDAP 身份验证