Well, after quite a long time, nearly a year, I am all set to publish my next post here. This has been a post that is long overdue and highly requested. I am going to write about how to secure a Spring MVC 4 web application using Spring Security. I am going to use Spring Boot to build a quick and configuration-less application. I have written in detail on how to use Spring Boot in a Spring Data Rest application here.

Spring Boot can be used with build tools such as Maven or Gradle. These build tools help you share jars between various applications, build your application and generate reports. I am going to use the same application that is provided in the spring security getting started guide but with JSP for views.

That is all! Now to run the application, right click project, run as Maven Build with the goal, clean install spring-boot:run

This will install the project with all necessary dependencies, generate war file in target folder and start the embedded tomcat server provided by spring boot. Open a browser and hit http://localhost:8080/ to see the home page,

On clicking the link for greeting message, user will be redirected to login page as shown below,

As you can see, the login page provides a simple form that captures a username and password and posts them to "/login". As configured, Spring Security provides a filter that intercepts that request and authenticates the user. If the user fails to authenticate, the page is redirected to "/login?error" and our page displays the appropriate error message. Upon successfully signing out, our application is sent to "/login?logout" and our page displays the appropriate success message.

User is redirected to login page after signing out, with a logout message,

If the credentials are wrong, user is redirected to login page with error message,

To know how to directly run the downloaded project, watch this video,

How it Works

First let me start with application setup. Throughout the implementation, we did not write any xml configuration and even web.xml is eliminated with the use of Spring Boot. Let me go step by step on how Spring Boot set up the application for us,

1. Once maven downloads all required libraries to the classpath (WEB-INF\lib), Spring Boot looks into the classpath and makes reasonable assumptions about what you’re missing, and adds it.

2. Spring Boot launches an application from a class which is annotated with @SpringBootApplication, so in our example it starts with 'Application.java'

@SpringBootApplication is a convenience annotation that adds all of the following:

-- @Configuration tags the class as a source of bean definitions for the application context.

-- @EnableAutoConfiguration tells Spring Boot to start adding beans based on classpath settings, other beans, and various property settings.

-- Normally you would add @EnableWebMvc for a Spring MVC app, but Spring Boot adds it automatically when it sees spring-webmvc on the classpath. This flags the application as a web application and activates key behaviors such as setting up a DispatcherServlet.

-- @ComponentScan tells Spring to look for other components, configurations, and services inside the same package as it is in. In this case it looks in to all classes inside the 'hello' package.

3. While 'hello' package is scanned, it will go through all classes with @Configuration and will register all configurations present. In our example, we have MvcConfig and WebSecurityConfig annotated with @Configuration

Spring Security

When spring-security is present in the classpath, Spring automatically secures all HTTP end points with basic authentication. To further customize the security settings, such as authenticating users against details stored in a database or autenticate only specific http endpoints not all etc. you should setup security configuration. In our example, we provide a simple in-memory authentication for all the pages except for the home page(home.jsp) and this is configured in WebSecurityConfig class.

The WebSecurityConfig class is annotated with @EnableWebMvcSecurity to enable Spring Security’s web security support and provide the Spring MVC integration. It also extends WebSecurityConfigurerAdapter and overrides a couple of its methods to set some specifics of the web security configuration. The configure(HttpSecurity) method defines which URL paths should be secured and which should not. Specifically, the "/" and "/home" paths are configured to not require any authentication. All other paths must be authenticated.

When a user successfully logs in, they will be redirected to the previously requested page that requires authentication. There is a custom "/login" page specified by loginPage(), and everyone is allowed to view it. As for the configure(AuthenticationManagerBuilder) method, it sets up an in-memory user store with a single user. That user is given a username of "user", a password of "password", and a role of "USER".

Last we need to provide the user a way to display the current username and Sign Out. Update the hello.html to say hello to the current user and contain a "Sign Out" form as shown below

CSRF Attack

You might have noticed myself placing hidden input type with name="${_csrf.parameterName}" and value="${_csrf.token}" in the login page and the page from where users log out. This is to protect the application against
Cross Site Request Forgery (CSRF) attacks.

CSRF protection is enabled by default with Java Configuration. You can disable it as well. If you are using Spring MVC <form:form> tag, the CsrfToken is automatically included. Since we are not using Spring form tag, I have used hidden inputs to send csrf tokens to the server. A detailed and a very clear explanation of CSRF support in Spring MVC is provided in this
article.

Note: I have added a static resource in the demo project for styling and I have excluded that in the tutorial for simplicity sake. I will write about how to use static resources such as javascript or css, while using Spring Security and Spring Boot in a separate article.