如何在分布在多个文件中的 Spring Security 中订购多个 <http> 元素

ebi*_*ebi 4 java spring spring-security

在 Spring Security 中,可以指定<http>导致多个 SecurityFilterChains 的多个配置。我使用该功能来保护与普通 Web 应用程序不同的 Rest API。web app 和rest api 都是在不同的模块(maven artifacts)中开发的。Spring 配置通过通配符模式在整个类路径 ( classpath*:/some-common-config-path/*.xml)中收集。

中 Web 应用程序的安全配置web-security-config.xml

<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://cxf.apache.org/configuration/beans http://cxf.apache.org/schemas/configuration/cxf-beans.xsd
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

  <!-- Security Config for web app -->
  <http use-expressions="true" auto-config="false" entry-point-ref="loginEntryPoint">
       ...
  </http>

  <!-- Security Config for static resources -->
  <http pattern="/static/**" security="none" />

  ...

</beans:beans>
Run Code Online (Sandbox Code Playgroud)

中 Rest API 的安全配置api-security-config.xml

<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://cxf.apache.org/configuration/beans http://cxf.apache.org/schemas/configuration/cxf-beans.xsd
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

  <http pattern="/api/**" use-expressions="true" create-session="stateless"
        authentication-manager-ref="apiAuthManager" entry-point-ref="restAuthenticationEntryPoint">
      <intercept-url pattern="/api/**" access="hasRole('REST_API')" />
      <http-basic />
  </http>

  ...

</beans:beans>
Run Code Online (Sandbox Code Playgroud)

问题是,类路径中两个模块的顺序是不可预测的,配置文件的解析顺序也是如此。在我的特定情况下api-security-config.xml,读取 web-security-config.xml应用程序上下文启动失败,但出现以下异常:

java.lang.IllegalArgumentException:在过滤器链中的其他模式之前定义了通用匹配模式 ('/**'),导致它们被忽略。请检查您的命名空间或 FilterChainProxy bean 配置中的顺序

所以我要做的是以某种方式指定<http>元素的顺序,以便在最通用的配置之前解析特定的配置。有没有可能做到这一点?

Rob*_*nch 5

目前没有办法分解 Spring Security 的 XML 配置并指定一个顺序,以确保您的 XML 以正确的顺序加载。实现这一目标的一种方法是执行以下操作:

创建由通用配置加载的 /some-common-config-path/security.xml 配置,该配置以正确的顺序导入两个配置(不在通用配置位置):

<import resource="/not-common-config-path/api-security-config.xml"/>
<import resource="/not-common-config-path/web-security-config.xml"/>
Run Code Online (Sandbox Code Playgroud)

您可以在 Spring Security 3.2 中使用 Java 配置并使用 @Order 注释来执行此操作。如文档中所示

@Configuration
@EnableWebSecurity
public class MultiHttpSecurityConfig {
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) { 
        auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }

    @Configuration
    @Order(1)                                                        
    public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
        protected void configure(HttpSecurity http) throws Exception {
            http
                .antMatcher("/api/**")                               
                .authorizeRequests()
                    .anyRequest().hasRole("ADMIN")
                    .and()
                .httpBasic();
        }
    }

    @Configuration                                                   
    public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .authorizeRequests()
                    .anyRequest().authenticated()
                    .and()
                .formLogin();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您愿意,也可以拆分这些配置。

要自动选择 Java 配置,您可以轻松地将类路径扫描添加到您的设置中。例如,如果您使用以 XML 为中心的配置并且所有 Java 配置都在包 com.example.config 中,则可以添加:

<!-- 
    enable processing of annotations such as @Autowired and @Configuration
    You may already have annotation-config
 -->
<context:annotation-config/>
<!-- Add any Java Configuration -->
<context:component-scan base-package="com.example.config"/>
Run Code Online (Sandbox Code Playgroud)

有关 XML 和 Java 配置的更多详细信息,请阅读参考资料中的Combining Java and XML Configuration