This tutorial shows you how to create Spring Security 4 Authentication Annotation XML Example. This example will demonstrate to secure a Spring MVC web application with authentication URL access.
Table of contents:
1. Project structure
2. Maven dependencies
3. Spring Security Configuration
4. Register security filter
5. Create Controller
6. Configure Spring MVC with Java Annotation Configuration
7. Configure the Dispatcher Servlet
8. Create views
9. Deploy Spring Security 4 Authentication Annotation XML Example
Other interesting posts you may like
Now, we are ready to create Spring Security 4 Authentication Annotation XML Example following step by step.
Project structure
Make sure your project looks similar to the following structure
Maven dependencies
We are using the latest version of Spring MVC and Spring Security in this example. One more thing, we are configuring our application using Java Annotation Configuration, we don’t use the web.xml anymore. We need to instruct Maven to ignore the web.xml file by setting the failOnMissingWebXml element to false. Below is the pom.xml file for our project.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javabycode.springsecurity</groupId> <artifactId>Spring-Security-Annotation-Example</artifactId> <version>1.0.0</version> <packaging>war</packaging> <name>Spring-Security-Annotation-Example</name> <properties> <springframework.version>4.3.0.RELEASE</springframework.version> <springsecurity.version>4.1.0.RELEASE</springsecurity.version> </properties> <dependencies> <!-- Spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${springframework.version}</version> </dependency> <!-- Spring Security --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>${springsecurity.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>${springsecurity.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> </dependencies> <build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.4</version> <configuration> <warSourceDirectory>src/main/webapp</warSourceDirectory> <warName>spring-security-annotation</warName> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </pluginManagement> <finalName>spring-security-annotation</finalName> </build> </project> |
Spring Security Configuration
We enable spring security in the application by creating Spring Security Java Configuration class. This class is responsible for protecting the URLs, validating username and password, redirecting to the log in form in the application.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
package com.javabycode.springsecurity.configuration; 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; @Configuration @EnableWebSecurity public class MySecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("javabycode").password("123456").roles("USER"); auth.inMemoryAuthentication().withUser("admin").password("admin123").roles("ADMIN"); auth.inMemoryAuthentication().withUser("root").password("root123").roles("ADMIN","ROOT"); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/").permitAll() .antMatchers("/admin/**").access("hasRole('ADMIN')") .antMatchers("/root/**").access("hasRole('ADMIN') and hasRole('ROOT')") .and().formLogin() .and().exceptionHandling().accessDeniedPage("/error"); } } |
Let’s dig deeper
The method configureGlobalSecurity(AuthenticationManagerBuilder auth) creates AuthenticationManagerBuilder with user credentials and appropriate roles. There are other authentication ways like JDBC, LDAP or other authentications. But we are using in-memory authentication in this example.
The method Configure makes HttpSecurity configuration for specific http requests. We are using antMathchers to restrict the specific requests here. Otherwise all requests will be applied by default.
We catch all the 403 cases (http access denied) and redirect to our error page by using exceptionHandling().accessDeniedPage()
The above security java configuration is equivalent with the below XML configuration:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<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-4.3.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.1.xsd"> <http auto-config="true" > <intercept-url pattern="/" access="permitAll" /> <intercept-url pattern="/admin**" access="hasRole('ADMIN')" /> <intercept-url pattern="/root**" access="hasRole('ADMIN') and hasRole('ROOT')" /> <form-login authentication-failure-url="/error" /> </http> <authentication-manager > <authentication-provider> <user-service> <user name="javabycode" password="123456" authorities="ROLE_USER" /> <user name="admin" password="admin123" authorities="ROLE_ADMIN" /> <user name="root" password="root123" authorities="ROLE_ADMIN,ROLE_ROOT" /> </user-service> </authentication-provider> </authentication-manager> </beans:beans> |
Register security filter
We create the class which extends AbstractSecurityWebApplicationInitializer to register spring security filter with the application. AbstractSecurityWebApplicationInitializer includes DelegatingFilterProxy and ContextLoaderListener.
1 2 3 4 5 6 7 |
package com.javabycode.springsecurity.configuration; import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; public class MySecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer { } |
The above security java configuration is equivalent with the below XML configuration:
1 2 3 4 5 6 7 8 9 |
<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> |
Create Controller
We create simple controller demonstrates authentication steps with every user roles. Notices that we use the method getPrincipal to get user name from Spring SecurityContext. Our controller should be implemented like below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
package com.javabycode.springsecurity.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class MyLoginController { @RequestMapping(value = { "/" }, method = RequestMethod.GET) public String welcomeView(ModelMap model) { model.addAttribute("message", "Welcome to my site. This is Spring Security Example"); return "index"; } @RequestMapping(value = "/admin", method = RequestMethod.GET) public String adminView(ModelMap model) { model.addAttribute("userName", getUserName()); return "admin"; } @RequestMapping(value = "/root", method = RequestMethod.GET) public String rootView(ModelMap model) { model.addAttribute("userName", getUserName()); return "root"; } @RequestMapping(value="/logout", method = RequestMethod.GET) public String logoutView (HttpServletRequest request, HttpServletResponse response) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null){ new SecurityContextLogoutHandler().logout(request, response, auth); } return "index"; } @RequestMapping(value = "/error", method = RequestMethod.GET) public String errorView(ModelMap model) { model.addAttribute("userName", getUserName()); return "error"; } private String getUserName(){ String userName = null; Object credential = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); if (credential instanceof UserDetails) { userName = ((UserDetails)credential).getUsername(); } else { userName = credential.toString(); } return userName; } } |
Configure Spring MVC with Java Annotation Configuration
If you are similar to configure Spring MVC with annotation you can skip over this step. Where as you can study about it by refering to the post Spring MVC Annotation Example or look into attached source code. We will not mention it here.
Configure the Dispatcher Servlet
If you are similar to configure the Dispatcher Servlet you can skip over this step. Where as you can study about it by refering to the post Spring MVC Annotation Example or look into attached source code. We will not mention it here.
Create Views
We need to create views to display messages of authentication results.
index.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Welcome page</title> </head> <body> ${message} <br> <a href="<c:url value="/admin" />">Login as Admin</a> </body> </html> |
admin.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Admin page</title> </head> <body> Welcome <strong>${userName}</strong>, You are authorized to access the Admin page. <br> <a href="<c:url value="/root" />">Login as Root</a> <br> <a href="<c:url value="/logout" />">Logout</a> </body> </html> |
root.jsp
1 2 3 4 5 6 7 8 9 10 11 12 |
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Root page</title> </head> <body> Welcome <strong>${userName}</strong>, You are authorized to access the Root page. <a href="<c:url value="/logout" />">Logout</a> </body> </html> |
error.jsp
1 2 3 4 5 6 7 8 9 10 11 12 |
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Error page</title> </head> <body> Sorry <strong>${userName}</strong>, You are not authorized to access this page. <a href="<c:url value="/logout" />">Logout</a> </body> </html> |
Deploy Spring Security 4 Authentication Annotation XML Example
After building the project by maven we deploy the file war on application server (Tomcat 8 for example). Run the URL http://localhost:8080/spring-security-annotation/ and the screen looks like this
Next, click the link “Login as Admin” on the above screen. The login form appears such as below
Login as user role
Then the error page appears such as below
Login as admin role with wrong password
Login again admin role and credentials (admin/admin123) the admin page appears like below
Repeat the above steps with root role and root credentials you will get the the same result.
That’s all on the tutorial Spring Security 4 Authentication Annotation XML Example. If you find my mistake please leave comment or feedback.
Download complete source code, click link below
Spring-Security-Annotation-Example.zip (336 downloads)