我正在尝试为基于Spring 3.2.8的纯Java配置应用程序添加安全性。我按照说明http://docs.spring.io/spring-security/site/docs/3.2.2.RELEASE/reference/htmlsingle/#jc
我已经完成了3.1节,文档说此时每个URL都需要身份验证,但没有一个(至少我可以加载每个URL)。它说它创建了一个Servlet过滤器等。
很明显,WebSecurityConfigurerAdapter子类本身是不够的。所以我看一下3.1.1节,它说下一步是将springSecurityFilterChain注册到WAR,然后继续说明在Servlet 3+环境中,我需要继承AbstractSecurityWebApplicationInitializer。但我已经在继承AbstractAnnotationConfigDispatcherServletInitializer。我应该有一个吗?在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
{
}
}
答案 0 :(得分:1)
根据https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#abstractsecuritywebapplicationinitializer-with-spring-mvc,您必须引入第二个WebApplicationInitializer,通常派生自AbstractSecurityWebApplicationInitializer
第二个WebApplicationInitializer会将属性注册为springFilterChain
答案 1 :(得分:0)
使用5.0.6 Spring Security版本进行回答:
您的想法和配置似乎正确,但我不确定是否将SecurityWebApplicationInitializer保留为静态内部类是否允许Spring查找它。可能是个问题。我按照上述说明进行了所有配置,并且一切正常,将我重定向到“ / login”页面。