Tomcat 7和AbstractSecurityWebApplicationInitializer不能一起工作

时间:2013-07-11 19:36:18

标签: java spring-security tomcat7 servlet-3.0

我正在关注此article尝试使用基本的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",

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

@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();
    }

}

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

@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;
//  }

}

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

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

但我总是收到这个错误:

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

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

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

然后

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);
}

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

我尝试使用@Order,但这样做无效,所以我尝试使用springSecurityFilterChain方法注册registerServletFilter,但我没有获得任何http-auth请求身份验证。 而且SecurityConfiguration甚至都没有被加载。

1 个答案:

答案 0 :(得分:7)

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

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
...
}

需要指出的其他一些事项:

  • 您不需要使用@Order,因为您没有添加任何其他过滤器
  • 您获得保护的唯一网址是上下文根(即/).
  • 您需要了解http need spring security java config example showing basic auth only
  • 中讨论的httpBasic()错误
  • 更新:我还应该指出,我已经记录了SPR-10660以支持@Enable*注释,而没有@Configuration。在解决之后,你的问题就会神奇地消失。