Spring security throws javax.servlet.ServletException: Failed to resolve view named 'j_spring_security_check'

I am trying to add Spring security with a personalized login page and database access to my Spring MVC application. It seems that my mapping is incorrect, as it cannot display j_spring_security_check .

To solve the problem, I looked at the following pages 1 , 2 , 3 , but so far I could not solve the problem.

If you don't have much time, read PART 2 below, this is where the edited section of the question begins. Otherwise, read both PART 1 and PART 2 .

PART 1

I also added the following lines to my web.xml , but the application returns the following exceptions.

  <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> Caused by: java.lang.IllegalStateException: Duplicate Filter registration for 'springSecurityFilterChain'. Check to ensure the Filter is only configured once. at org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer.registerFilter(AbstractSecurityWebApplicationInitializer.java:215) at org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer.insertSpringSecurityFilterChain(AbstractSecurityWebApplicationInitializer.java:147) at org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer.onStartup(AbstractSecurityWebApplicationInitializer.java:121) at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:175) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5423) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) ... 6 more Jun 13, 2015 2:44:54 PM org.apache.catalina.core.ContainerBase startInternal SEVERE: A child container failed during start java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost]] at java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.util.concurrent.FutureTask.get(FutureTask.java:188) at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1123) at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:302) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:732) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) at org.apache.catalina.startup.Catalina.start(Catalina.java:691) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:322) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:456) Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost]] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549) at java.util.concurrent.FutureTask.run(FutureTask.java:262) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:744) Caused by: org.apache.catalina.LifecycleException: A child container failed during start at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1131) at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:800) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) ... 6 more Jun 13, 2015 2:44:54 PM org.apache.catalina.startup.Catalina start SEVERE: The required Server component failed to start so Tomcat is unable to start. org.apache.catalina.LifecycleException: Failed to start component [StandardServer[8005]] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154) at org.apache.catalina.startup.Catalina.start(Catalina.java:691) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:322) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:456) Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardService[Catalina]] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154) at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:732) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) ... 7 more Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina]] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154) at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) ... 9 more Caused by: org.apache.catalina.LifecycleException: A child container failed during start at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1131) at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:302) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) ... 11 more 

Without adding this filter after the form is submitted, the request will be captured by the controller.

 @Controller public class MainController { @RequestMapping("/{viewName}") public String index(@PathVariable String viewName) { ... } 

web.xml

 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <listener> <listener-class>org.apache.tiles.extras.complete.CompleteAutoloadTilesListener</listener-class> </listener> <servlet> <servlet-name>my</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- <listener> --> <!-- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> --> <!-- </listener> --> <!-- <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> --> <servlet-mapping> <servlet-name>my</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/config/my-security.xml </param-value> </context-param> </web-app> 

my-security.xml

 <beans:beans xmlns="http://www.springframework.org/schema/security" 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 auto-config="true" access-denied-page="/notFound.jsp" use-expressions="true"> <intercept-url pattern="/" access="permitAll" /> </http> <!-- <beans:import resource="security-db.xml" /> --> <authentication-manager> <authentication-provider> <user-service> <user name="alex" password="123456" authorities="ROLE_USER" /> <user name="mkyong" password="123456" authorities="ROLE_USER, ROLE_ADMIN" /> </user-service> </authentication-provider> </authentication-manager> </beans:beans> 

Appconfig.java

 @EnableWebMvc @Configuration @ComponentScan({ "com.myproject.*" }) @EnableTransactionManagement @Import({ SecurityConfig.class }) public class AppConfig { @Bean public SessionFactory sessionFactory() { LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder( dataSource()); builder.scanPackages("com.myproject.model").addProperties( getHibernateProperties()); return builder.buildSessionFactory(); } private Properties getHibernateProperties() { Properties prop = new Properties(); prop.put("hibernate.format_sql", "true"); prop.put("hiberate.show_sql", "true"); prop.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect"); return prop; } @Bean(name = "dataSource") public BasicDataSource dataSource() { BasicDataSource ds = new BasicDataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/test"); ds.setUsername("jack"); ds.setPassword("jack"); return ds; } @Bean public HibernateTransactionManager txManager() { return new HibernateTransactionManager(sessionFactory()); } } 

SecurityConfig.java

 @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired @Qualifier("userDetailsService") UserDetailsService userDetailsService; @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder( passwordEncoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().antMatchers("/profile/**") .access("hasRole('ADMIN')").and().formLogin() .loginPage("/signin").failureUrl("/signin?error") .usernameParameter("username").passwordParameter("password") .and().logout().logoutSuccessUrl("/index").and().csrf().and() .exceptionHandling().accessDeniedPage("/403"); } @Bean public PasswordEncoder passwordEncoder() { PasswordEncoder encoder = new BCryptPasswordEncoder(); return encoder; } } 

SpringMVCInitializer.java

 import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[] { AppConfig.class }; } @Override protected Class<?>[] getServletConfigClasses() { return null; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } } 

LoginController.java

 @Controller public class LoginController { @RequestMapping(value = "/login", method = RequestMethod.GET) public ModelAndView login( @RequestParam(value = "error", required = false) String error, @RequestParam(value = "logout", required = false) String logout) { ModelAndView model = new ModelAndView(); if (error != null) { model.addObject("error", "Invalid username and password!"); } if (logout != null) { model.addObject("msg", "You've been logged out successfully."); } model.setViewName("login"); return model; } } 

**

PART 2

Based on Thomas suggestions, I changed the code as follows

**

web.xml

 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <listener> <listener-class>org.apache.tiles.extras.complete.CompleteAutoloadTilesListener</listener-class> </listener> <servlet> <servlet-name>my</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>my</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app> 

Appconfig.java

 @EnableWebMvc @Configuration @ComponentScan({ "com.myproject" }) @EnableTransactionManagement @Import({ SecurityConfig.class }) public class AppConfig { @Bean public SessionFactory sessionFactory() { LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder( dataSource()); builder.scanPackages("com.myproject.model").addProperties( getHibernateProperties()); return builder.buildSessionFactory(); } private Properties getHibernateProperties() { Properties prop = new Properties(); prop.put("hibernate.format_sql", "true"); prop.put("hiberate.show_sql", "true"); prop.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect"); return prop; } @Bean(name = "dataSource") public BasicDataSource dataSource() { BasicDataSource ds = new BasicDataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/test"); ds.setUsername("jack"); ds.setPassword("jack"); return ds; } @Bean public HibernateTransactionManager txManager() { return new HibernateTransactionManager(sessionFactory()); } } 

SecurityConfig.java

 @Configuration @EnableWebMvcSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired @Qualifier("userDetailsService") UserDetailsService userDetailsService; @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("user").password("password").roles("USER"); // auth.userDetailsService(userDetailsService).passwordEncoder( // passwordEncoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().antMatchers("/profile/**") .access("hasRole('ADMIN')").and().formLogin() .loginPage("/login").failureUrl("/login?error") .and().logout().logoutSuccessUrl("/index").and().csrf().and() .exceptionHandling().accessDeniedPage("/403"); } @Bean public PasswordEncoder passwordEncoder() { PasswordEncoder encoder = new BCryptPasswordEncoder(); return encoder; } } 

SpringMVCInitializer.java

 public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[] { AppConfig.class }; } @Override protected Class<?>[] getServletConfigClasses() { return null; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } } 

Maincontroller

 @Controller public class MainController { @RequestMapping("/{viewName}") public String index(@PathVariable String viewName) { System.err.println("View Name is :" + viewName); if (isValidView(viewName)) { return viewName; } return null; } 

As for MainController, I process static pages like www.myproject.com/index, www.myproject.com/contactus, etc. My other question on this issue: here

+6
source share
2 answers

I highly recommend that you follow either Java or XML configurations. I personally prefer Java configuration.

  • Remove all Spring Security-related XML configurations and create the following files.
  • Change permissions addresses for everything you have.

     public class MessageSecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer { //register the springSecurityFilterChain with the war } public class MessageWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[] { SecurityConfig.class }; //make sure your config file gets loaded } @Override protected Class<?>[] getServletConfigClasses() { // TODO Auto-generated method stub return null; } @Override protected String[] getServletMappings() { // TODO Auto-generated method stub return null; } @Configuration @EnableWebMvcSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { System.err.println("in here"); auth.inMemoryAuthentication().withUser(" user@yahoo.com ") .password("password").roles("USER"); //access to inmemory credentials } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/resources/**", "/", "/index", "/aboutus") .permitAll() //allow access to your static pages and resources .antMatchers("/profile/**") .hasRole("USER") //profile address is only available to users ( do not need to add ROLE_ as Spring does it for you) .and() //and is equivalent of end tag in XML .formLogin().loginPage("/signin").failureUrl("/signin?error") .permitAll().and().logout().logoutUrl("/singout").permitAll(); } 

For further explanation and access to the database, refer to the documentation

+1
source

There are several problems in the code. Most importantly, you are mixing Java configuration and XML configuration for Spring Security. Decide which configuration you prefer to use. In my answer, I will focus on Java based configuration, as I completely remove the XML configuration from your code.

In your case, the @EnableWebSecurity annotation by default already registers the appropriate filters. But if you use Spring MVC, it should be @EnableWebMvcSecurity .

Also, take a look at the HttpSecurity configuration:

  protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().antMatchers("/profile/**") .access("hasRole('ADMIN')").and().formLogin() .loginPage("/signin").failureUrl("/signin?error") .usernameParameter("username").passwordParameter("password") .and().logout().logoutSuccessUrl("/index").and().csrf().and() .exceptionHandling().accessDeniedPage("/403"); } 

You obviously say that the login page will be in /signin , but in your LoginController this is the mapping for /login . And why are you configuring .usernameParameter("username") .passwordParameter("password") ? This is already done in Spring's default setting by default.

You should also add the SecurityInitializer class, which in Spring Security 3.2 might look like this:

 public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer { public SecurityInitializer() { super(SecurityConfig.class); } } 

So, to summarize, the basic steps to add Spring Security to your project are as follows:

  • Add appropriate (Maven, Gradle) dependencies for Spring Security;
  • Configure Spring security class annotated with @EnableWebMvcSecurity , especially in the configureGlobal(...) and configure(...) methods;
  • Register a class that extends AbstractSecurityWebApplicationInitializer ;
  • Provide a display of the controller login page and record the user form on the JSP page.

The main login form may look like this:

  <form name='loginForm' method='POST'> <table> <tr> <td>User:</td> <td><input type='text' name='username' value=''></td> </tr> <tr> <td>Password:</td> <td><input type='password' name='password' /></td> </tr> <tr> <td colspan='2'><input name="submit" type="submit" value="submit" /></td> </tr> </table> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> </form> 

These basic steps include Spring Security in your project. For more information, good tutorials: http://docs.spring.io/spring-security/site/docs/3.2.x/guides/hellomvc.html http://docs.spring.io/spring-security/ site / docs / 3.2.x / guides / form.html

Good luck :)

+3
source

Source: https://habr.com/ru/post/989049/


All Articles