AbstractSecurityWebApplicationInitializer与AbstractAnnotationConfigDispatcherServletInitializer

我正在尝试为基于Spring 3.2.8的纯Java配置应用程序添加安全性。 我按照说明http://docs.spring.io/spring-security/site/docs/3.2.2.RELEASE/reference/htmlsingle/#jc

我已经完成了3.1节,文档说这时每个URL都应该要求身份validation,但没有一个(至少我可以加载每个URL)。 它说它创建了一个Servletfilter等。

很明显,WebSecurityConfigurerAdapter子类本身是不够的。 所以我看一下3.1.1节,它说下一步是将springSecurityFilterChain注册到WAR,然后继续说明在Servlet 3+环境中,我需要inheritanceAbstractSecurityWebApplicationInitializer。 但我已经在inheritanceAbstractAnnotationConfigDispatcherServletInitializer。 我应该有一个吗? 在AbstractSecurityWebApplicationInitializer JavaDoc中有一些关于排序的讨论,暗示我应该有多个初始化类。

在所有这些中,它还说要将WebSecurityConfigurerAdapter子类添加到getRootConfigClasses()(尽管该示例没有显示其他Spring启动文档的“AppConfig”;而且,仅此一项还不够)。

所以我尝试添加另一个初始化类。 我的所有其他类都是我的AbstractAnnotationConfigDispatcherServletInitializer子类的公共静态内部类,所以我把另一个放在那里作为AbstractSecurityWebApplicationInitializer子类(而不是创建一个单独的.java文件)。

WARNING com.caucho.server.webapp.WebApp setConfigException: java.lang.UnsupportedOperationException: unimplemented at com.caucho.server.webapp.ServletContextImpl.setSessionTrackingModes(ServletContextImpl.java:552) at org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer.onStartup(AbstractSecurityWebApplicationInitializer.java:120) at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:174) at com.caucho.server.webapp.WebApp.callInitializer(WebApp.java:3471) at com.caucho.server.webapp.WebApp.callInitializers(WebApp.java:3439) at com.caucho.server.webapp.WebApp.startImpl(WebApp.java:3661) at com.caucho.server.webapp.WebApp$StartupTask.run(WebApp.java:5196) at com.caucho.env.thread2.ResinThread2.runTasks(ResinThread2.java:173) at com.caucho.env.thread2.ResinThread2.run(ResinThread2.java:118) 

我尝试添加订购无济于事。 我的整个配置:

  package com.latencyzero.satdb.web; // // Java Imports // import java.util.Properties; import java.util.ResourceBundle; import javax.naming.InitialContext; import javax.servlet.ServletContext; import javax.sql.DataSource; // // Library Imports // import org.apache.log4j.Logger; import org.apache.log4j.BasicConfigurator; import org.apache.log4j.xml.DOMConfigurator; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; import org.springframework.stereotype.Controller; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.web.context.ContextLoaderListener; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.view.InternalResourceViewResolver; // // Project Imports // /** There are still some things that get configured in the container. This app was developed using Resin. Things configured in resin's XML config for this app include the data source, error page, key store password for Apple Push Notifications (which should move to the DB). */ public class WebappInitializer extends org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class[] getRootConfigClasses() { Class[] classes = { AppConfig.class, SecurityConfig.class }; return classes; } @Override protected Class[] getServletConfigClasses() { Class[] classes = { WebConfig.class }; return classes; } @Override protected java.lang.String[] getServletMappings() { String[] mappings = { "/" }; return mappings; } @Override protected javax.servlet.Filter[] getServletFilters() { return new javax.servlet.Filter[] { new org.springframework.orm.hibernate3.support.OpenSessionInViewFilter(), }; } /** ******************************************************************************************************************* App context configuration. Hibernate config (data access, transactions, data model). */ @Configuration @EnableAsync @EnableTransactionManagement @ComponentScan(basePackages = { "com.mymodelanddao", }) public static class AppConfig { @Bean public org.springframework.jndi.JndiObjectFactoryBean dataSource() { org.springframework.jndi.JndiObjectFactoryBean bean = new org.springframework.jndi.JndiObjectFactoryBean(); bean.setJndiName("java:comp/env/jdbc/db"); return bean; } @Bean public org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean sessionFactory() { DataSource dataSource = (DataSource) dataSource().getObject(); org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean bean = new org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean(); bean.setDataSource(dataSource); // TODO: Do we need to scan this, since it's done as part of @ComponentScan? bean.setPackagesToScan(new String[] {"com.latencyzero.satdb.model"}); Properties props = new Properties(); props.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect"); props.setProperty("hibernate.cache.provider_class", "org.hibernate.cache.NoCacheProvider"); props.setProperty("hibernate.jdbc.batch_size", "200"); props.setProperty("hibernate.show_sql", "false"); props.setProperty("hibernate.format_sql", "true"); props.setProperty("hibernate.use_sql_comments", "false"); props.setProperty("hibernate.generate_statistics", "true"); bean.setHibernateProperties(props); return bean; } @Bean public PlatformTransactionManager transactionManager() { SessionFactory sf = sessionFactory().getObject(); org.springframework.orm.hibernate3.HibernateTransactionManager bean = new org.springframework.orm.hibernate3.HibernateTransactionManager(); bean.setSessionFactory(sf); return bean; } private static Logger sLogger = Logger.getLogger(AppConfig.class); } /** ******************************************************************************************************************* Web context configuration. */ @Configuration @EnableWebMvc @ComponentScan(basePackageClasses = { com.mycontrollerclasses }) public static class WebConfig extends org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter { @Bean public InternalResourceViewResolver getInternalResourceViewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/jsp/"); resolver.setSuffix(".jsp"); return resolver; } @Bean public org.springframework.web.multipart.commons.CommonsMultipartResolver multipartResolver() { return new org.springframework.web.multipart.commons.CommonsMultipartResolver(); } @Override public void addResourceHandlers(ResourceHandlerRegistry inRegistry) { inRegistry.addResourceHandler("/assets/**").addResourceLocations("/assets/").setCachePeriod(31556926); inRegistry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926); inRegistry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926); } private static Logger sLogger = Logger.getLogger(WebConfig.class); } /** ******************************************************************************************************************* Security configuration. */ @Configuration @EnableWebMvcSecurity public static class SecurityConfig extends org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder inAuth) throws Exception { sLogger.warn("configureGlobal ================================================="); inAuth .inMemoryAuthentication() .withUser("user") .password("password") .roles("USER"); } private static Logger sLogger = Logger.getLogger(SecurityConfig.class); } public static class SecurityWebApplicationInitializer extends org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer { } } 

根据https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#abstractsecuritywebapplicationinitializer-with-spring-mvc ,您必须引入第二个WebApplicationInitializer,通常派生自AbstractSecurityWebApplicationInitializer

第二个WebApplicationInitializer将为springFilterChain注册属性

使用5.0.6 Spring Security版本回答:

  1. @EnableWebSecurity已经包含@Configuration,
    因此指定两者都是多余的
  2. 您确实需要第二个appinitializer,它扩展了AbstractSecurityWebApplicationInitializer。 你的似乎没问题
  3. 你的getRootConfigClasses也行。
    你真的应该在那里注册SecurityConfig.class。

你的想法和配置似乎是正确的,除了我不确定是否将SecurityWebApplicationInitializer保持为静态内部类允许Spring找到它。 也许这可能是一个问题。 我按照上面提到的说明完成了所有配置,一切都像魅力一样,将我重定向到“/ login”页面。