I am a little new to spring and still confused by all the configurations. I went by several different tutorials and it seems like everyone does things differently. I have a spring application which runs fine through Eclipse using the tomcat plugin. However when exporting a war file to tomcat itself tomcat doesn't start and throws
SEVERE: ContainerBase.addChild: start org.apache.catalina.LifecycleException: Failed to start component
Caused by: java.lang.IllegalStateException: Duplicate Filter registration for 'springSecuirtyFilterChain'. Check to insure the Filter is only configured once!
See picture for full stack trace.
After commenting out springSecurityFilterChain in web.xml, whether dataSource is autowired or not gives one or two errors.
If dataSource is autowired then I just get an error saying creating bean securityConfig failed and that there is no bean found for dependency.
If I leave dataSource not autowired (like the code I have which works in Eclipse) then I get an IllegalArgumentException: Property 'dataSource' is required.
Also in order to not get a multiple ContextLoader definition error I have to comment out the ContextLoaderListener in web xml.
From what I've seen the problem lies in using xml and java for configurations but I can't pinpoint exactly what is wrong.
I found a similar question but was unable to solve my problem. Where do I define `springSecurityFilterChain` bean? Adding a bean class pointing to my securityConfig put in spring-security.xml didn't help.
Thanks!
Below is the code which works totally fine when running in Eclipse.
web.xml
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<!-- Spring MVC -->
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>InitServlet</servlet-name>
<servlet-class>servlet.InitServlet</servlet-class>
<init-param>
<param-name>configfile</param-name>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet>
<servlet-name>AdminServlet</servlet-name>
<servlet-class>servlet.admin.AdminServlet</servlet-class>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet>
<servlet-name>UserServlet</servlet-name>
<servlet-class>servlet.user.UserServlet</servlet-class>
<load-on-startup>4</load-on-startup>
</servlet>
<servlet>
<servlet-name>SignupUserServlet</servlet-name>
<servlet-class>servlet.user.SignupUserServlet</servlet-class>
<load-on-startup>5</load-on-startup>
</servlet>
<servlet>
<servlet-name>ReceiveFile</servlet-name>
<servlet-class>servlet.user.ReceiveFile</servlet-class>
<load-on-startup>6</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/pages/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>AdminServlet</servlet-name>
<url-pattern>/AdminServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>UserServlet</servlet-name>
<url-pattern>/UserServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>SignupUserServlet</servlet-name>
<url-pattern>/SignupUserServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ReceiveFile</servlet-name>
<url-pattern>/ReceiveFile</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-security.xml,
/WEB-INF/spring-database.xml
</param-value>
</context-param>
<!-- Spring Security -->
<!-- This is to allow enctype="multipart/form-data" to upload and not throw an access denied page.
See bottom of http://docs.spring.io/spring-security/site/docs/3.2.0.CI-SNAPSHOT/reference/html/csrf.html for more info.-->
<filter>
<filter-name>MultipartFilter</filter-name>
<filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>MultipartFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
SecuirtyConfig.java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
DataSource dataSource;
/* @Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
} */
@Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select username,password, enabled from test_users where username=?")
.authoritiesByUsernameQuery("select username, role from test_user_roles where username=?");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/res/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/loginDatabase.html")
.permitAll();
}
}
AppConfig.java
@EnableWebMvc
@Configuration
@ComponentScan({"security.spring"})
@Import({ SecurityConfig.class })
public class AppConfig {
@Bean(name = "dataSource")
public DriverManagerDataSource dataSource() {
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
driverManagerDataSource.setUrl("****");
driverManagerDataSource.setUsername("**");
driverManagerDataSource.setPassword("**");
return driverManagerDataSource;
}
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/pages/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
spring-security.xml
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="spring.*" />
<!-- enable use-expressions -->
<http auto-config="true" use-expressions="true">
<!-- login page must be available to all. The order matters, if this is after something which secures the page this will fail. -->
<!-- <intercept-url pattern="/SignupUserServlet" access="permitAll"/> -->
<!-- <intercept-url pattern="/pages/ReceiveFile" access="permitAll()"/>
<intercept-url pattern="/pages/fileUpdate2" access="permitAll()"/>
<intercept-url pattern="/pages/login" access="permitAll()" /> -->
<intercept-url pattern="/pages/admin/**" access="hasRole('_admin')" />
<intercept-url pattern="/pages/trade/**" access="hasRole('_trader')" />
<intercept-url pattern="/pages/discover/**" access="hasRole('_users')" />
<!-- access denied page -->
<access-denied-handler error-page="/pages/403" />
<form-login
login-page="/pages/login"
default-target-url="/pages/common/redirectportal"
authentication-failure-url="/pages/login?error"
username-parameter="username"
password-parameter="password" />
<logout logout-url="/pages/logout" logout-success-url="/pages/login?logout" />
<!-- enable csrf protection -->
<!-- currently off for testing... <csrf/> -->
</http>
<!-- Select users and user_roles from database -->
<authentication-manager>
<authentication-provider ref="customAuthenticationProvider"/>
<!--<jdbc-user-service data-source-ref="dataSource"
users-by-username-query=
"select email,pwhash, enabled from users where email=?"
authorities-by-username-query=
"select email, groupname from usergroups where email =? " />
</authentication-provider> -->
</authentication-manager>
</beans:beans>