Tomcat 7和AbstractSecurityWebApplicationInitializer不能一起工作

die*_*rre 2 java spring-security servlet-3.0 tomcat7

我正在关注这篇文章,尝试使用基本的http-auth而不使用web.xml

我正在使用Tomcat 7.0.41,这些是我对gradle的依赖:

  ext.springVersion =  "3.2.1.RELEASE"
  compile "org.springframework:spring-jdbc:$springVersion",
          "org.springframework:spring-context:$springVersion",
          "org.springframework:spring-web:$springVersion",
          "org.springframework:spring-webmvc:$springVersion",
          "org.springframework.security:spring-security-core:3.2.0.M2",
          "org.springframework.security:spring-security-web:3.2.0.M2",
          "org.springframework.security:spring-security-config:3.2.0.M2",
Run Code Online (Sandbox Code Playgroud)

根据教程,我定义了以下内容

@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void registerAuthentication(AuthenticationManagerBuilder auth)
            throws Exception {
        auth.inMemoryAuthentication().withUser("admin").password("admin")
                .roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeUrls().antMatchers("/").hasRole("USER")
                .and().httpBasic();
    }

}
Run Code Online (Sandbox Code Playgroud)

然后将该类添加到初始化器中,如下所示:

@Order(1)
public class ServletConfiguration extends
        AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { SecurityConfiguration.class };
        // return null;
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { AppConfiguration.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

//  @Override
//  protected Dynamic registerServletFilter(ServletContext servletContext,
//          Filter filter) {
//      Dynamic securityFilter = servletContext.addFilter(
//              "springSecurityFilterChain", DelegatingFilterProxy.class);
//      securityFilter.addMappingForUrlPatterns(
//              EnumSet.allOf(DispatcherType.class), false, "/*");
//      return securityFilter;
//  }

}
Run Code Online (Sandbox Code Playgroud)

最后添加了一个类来初始化springSecurityFilterChain:

@Order(2)
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer  {
@Override
protected void afterSpringSecurityFilterChain(ServletContext servletContext) {
    System.out.println("afterSpringSecurityFilterChain");
    super.afterSpringSecurityFilterChain(servletContext);
}
}
Run Code Online (Sandbox Code Playgroud)

但我总是得到这个错误:

DEBUG: org.springframework.jndi.JndiPropertySource - JNDI lookup for name [spring.liveBeansView.mbeanDomain] threw NamingException with message: Name [spring.liveBeansView.mbeanDomain] is not bound in this Context. Unable to find [spring.liveBeansView.mbeanDomain].. Returning null.
Jul 11, 2013 9:22:24 PM org.apache.catalina.core.StandardContext filterStart
SEVERE: Exception starting filter springSecurityFilterChain
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'springSecurityFilterChain' is defined
Run Code Online (Sandbox Code Playgroud)

我不是为什么,因为当我调试服务器初始化时,实际上这两个方法被调用:

@Override
public final void onStartup(ServletContext servletContext)
        throws ServletException {
    if(enableHttpSessionEventPublisher()) {
        servletContext.addListener(HttpSessionEventPublisher.class);
    }
    insertSpringSecurityFilterChain(servletContext);
    afterSpringSecurityFilterChain(servletContext);
}
Run Code Online (Sandbox Code Playgroud)

然后

private void insertSpringSecurityFilterChain(ServletContext servletContext) {
    String filterName = "springSecurityFilterChain";
    DelegatingFilterProxy springSecurityFilterChain = new DelegatingFilterProxy(filterName);
    String contextAttribute = getWebApplicationContextAttribute();
    if(contextAttribute != null) {
        springSecurityFilterChain.setContextAttribute(contextAttribute);
    }
    registerFilter(servletContext, true, filterName, springSecurityFilterChain);
}
Run Code Online (Sandbox Code Playgroud)

所以实际上过滤器被创建了.但它会在某处丢失.

我尝试使用@Order,但这没有做任何事情,所以我尝试springSecurityFilterChain使用该registerServletFilter方法注册,但我没有得到任何http-auth请求身份验证.而且SecurityConfiguration甚至没有加载.

Rob*_*nch 7

SecurityInitializer创建DelegatingFilterProxy,用于通过名称springSecurityFilterChain查找bean.springSecurityFilterChain是使用@EnableWebSecurity创建的.问题是你缺少@Configuration注释(没有它,Root ApplicationContext甚至不会尝试加载SecurityConfiguration).具体来说,您要执行以下操作:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
...
}
Run Code Online (Sandbox Code Playgroud)

还需要指出一些额外的事情:

  • 您不需要使用,@Order因为您没有添加任何其他过滤器
  • 您保护的唯一URL是上下文根(即/).
  • 您将需要了解httpBasic()的错误,该错误在需要spring security java配置示例时讨论,仅显示基本身份验证
  • 更新:我还应该指出,我已经记录了SPR-10660,以支持@Enable*注释,而无需@Configuration使用它们.在解决之后,你的问题会神奇地消失.