<!-- Spring Security Web --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>${spring.security.version}</version> </dependency> <!-- Spring Security Config --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>${spring.security.version}</version> </dependency>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Spring Security Basic Demo (Java Config)</title> </head> <body> <div align="center"> <h1>Spring Security Basic Demo (Java Config)</h1> <a href="/admin">Go to Administrator Page</a> </div> </body> </html>As you can see, this is very simple page with a heading “Spring Security Basic Demo (Java Config)” and a hyperlink to the administrator page which requires authentication to access.
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ page language="java" session="true" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Spring Security Basic Demo (Java Config)</title> </head> <body> <div align="center"> <h1>${title}</h1> <h2>${message}</h2> <c:if test="${pageContext.request.userPrincipal.name != null}"> <h2>Welcome : ${pageContext.request.userPrincipal.name} | <a href="/<c:url value="/logout" />" > Logout</a></h2> </c:if> </div> </body> </html>This is the administrator page which requires authentication and authorization to access. We use JSTL expressions to display the title and message in the model. If the user is logged in, display his username along with a logout link.
package net.codejava.spring; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; /** * Spring Web MVC Security Java Config Demo Project * Primary controller of the application. * * @author www.codejava.net * */ @Controller public class MainController { @RequestMapping(value="/", method = RequestMethod.GET) public ModelAndView visitHome() { return new ModelAndView("index"); } @RequestMapping(value="/admin", method = RequestMethod.GET) public ModelAndView visitAdmin() { ModelAndView model = new ModelAndView("admin"); model.addObject("title", "Admministrator Control Panel"); model.addObject("message", "This page demonstrates how to use Spring security."); return model; } }As you can see, this controller is designed to handle 2 requests:
package net.codejava.spring; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; /** * Spring Web MVC Security Java Config Demo Project * Bootstraps Spring Dispacher Servlet in Servlet 3.0+ environment. * * @author www.codejava.net * */ public class SpringWebAppInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext(); appContext.register(MvcConfig.class); ServletRegistration.Dynamic dispatcher = servletContext.addServlet( "SpringDispatcher", new DispatcherServlet(appContext)); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/"); } }Here, the SpringWebAppInitializeris a type of WebApplicationInitializerwhich is bootstrapped automatically by any Servlet 3.0+ container (See more: Bootstrapping a Spring Web MVC application programmatically).The above code is equivalent to the following XML snippet in the web.xml:
<servlet> <servlet-name>SpringController</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>SpringController</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
package net.codejava.spring; import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; /** * Spring Web MVC Security Java Config Demo Project * Bootstraps Spring Security Filter. * * @author www.codejava.net * */ public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer { public SecurityWebApplicationInitializer() { super(SecurityConfig.class); } }It’s equivalent to the following XML snippet in the web.xml file:
<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>Note that the SecurityWebApplicationInitializerclass passes SecurityConfig.classto its super’s constructor, which tells Spring Security looks for configuration in the class named SecurityConfig- which is described below.
package net.codejava.spring; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; /** * Spring Web MVC Security Java Config Demo Project * Configures authentication and authorization for the application. * * @author www.codejava.net * */ @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("admin").password("nimda").roles("ADMIN"); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/").permitAll() .antMatchers("/admin**").access("hasRole('ADMIN')") .and().formLogin(); http.csrf().disable(); } }This is equivalent to the following configuration in XML:
<http auto-config="true"> <intercept-url pattern="/admin**" access="hasRole('ADMIN')" /> <csrf disabled="true" /> </http> <authentication-manager> <authentication-provider> <user-service> <user name="admin" password="nimda" authorities="ADMIN" /> </user-service> </authentication-provider> </authentication-manager>Note that we disable CSRF for the sake of simplicity in this tutorial:
http.csrf().disable();That tells Spring Security to intercept the /logout link as an HTTP GET request. In production, you should enable CSRF for best security practice.
package net.codejava.spring; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.view.InternalResourceViewResolver; /** * Spring Web MVC Security Java Config Demo Project * Configures Spring MVC stuffs. * * @author www.codejava.net * */ @Configuration @ComponentScan("net.codejava.spring") public class MvcConfig { @Bean(name = "viewResolver") public InternalResourceViewResolver getViewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/WEB-INF/views/"); viewResolver.setSuffix(".jsp"); return viewResolver; } }As you can see, we configure this InternalResourceViewResolverbean to resolve logical view names to physical JSP pages. It's equivalent to the following XML:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean>
http://localhost:8080/SpringMVCSecurityJavaConfig
The home page appears:Click on the hyperlink Go to Administrator Page (it’s equivalent to type the URL: http://localhost:8080/SpringMVCSecurityJavaConfig/admin), Spring automatically generates a login page looks like this:First, let’s type an invalid username and password, Spring security automatically generates an error message in red at the top of the form, which is looking like this:Next, let’s type the correct username and password (admin and nimda, as per configured in this application), Spring security authenticates the login and returns the administrator page as follows:Awesome! Now, let’s test the logout functionality. Click on the Logout link, Spring security filter automatically intercepts the/logout URL, invalidates the session and take you to the login page again:Notice the message ‘You have been logged out’ is displayed in green at the top of the form, and the URL got changed to http://localhost:8080/ SpringMVCSecurityJavaConfig/login?logoutTo make sure Spring security already invalidated the session, let’s try to access the page http://localhost:8080/SpringMVCSecurityJavaConfig/admin again, we will see the login page. It’s working seamlessly!Perfect! We’ve done a basic Spring Web MVC Security project with Java configuration. References: