Today we will learn about Spring Security Login Example. Before reading this post, please go through my previous post at “Introduction to Spring 4 Security” to get some basics.
In this post, we are going to develop Spring 4 MVC Security Web Application to provide Login and Logout features by using In-Memory option. This example uses Spring Java Config with Spring Annotations, that means without using web.xml and Spring XML Configuration(Old Style). If you are not familiar with Spring 3.x Security Module, please go through the following posts first to taste the Spring Security Recipe.
Spring 4 Security Module supports the following options to store and manage User Credentials:
We will use “In-Memory Store” option in this example. We will discuss other options in my coming posts. We are going to use Spring 4.0.2.RELEASE, Spring STS 3.7 Suite IDE, Spring TC Server 3.1 with Java 1.8 and Maven build tool to develop this example.
We are going to develop a Login and Logout logic using Spring 4 Security Features. The main aim of this application is that developing an application without using “web.xml” and without writing a single line of Spring XML Beans Configuration. That means we are going to use Spring Java Config feature with Spring Annotations. We will develop this application with the following features:
Please use the following steps to develop and explore this Spring 4 Security Simple Login Example.
Project Name : SpringMVCSecruityMavenApp
<?xml version="1.0" encoding="UTF-8"?>
<project
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="https://maven.apache.org/POM/4.0.0"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.journaldev</groupId>
<artifactId>SpringMVCSecruityMavenApp</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<properties>
<java.version>1.8</java.version>
<spring.version>4.0.2.RELEASE</spring.version>
<spring.security.version>4.0.2.RELEASE</spring.security.version>
<servlet.api.version>3.1.0</servlet.api.version>
<jsp.api.version>2.2</jsp.api.version>
<jstl.version>1.2</jstl.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.api.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>${jsp.api.version}</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
</dependencies>
<build>
<finalName>SpringMVCSecruityMavenApp</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
NOTE:- If you are not aware of “<failOnMissingWebXml>” flag, please read at the end of this post to get a good understanding of this element usage.- First, Develop Login Controller by using Spring’s @Controller annotation. LoginController.java
package com.journaldev.spring.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class LoginController {
@RequestMapping(value = { "/"}, method = RequestMethod.GET)
public ModelAndView welcomePage() {
ModelAndView model = new ModelAndView();
model.setViewName("welcomePage");
return model;
}
@RequestMapping(value = { "/homePage"}, method = RequestMethod.GET)
public ModelAndView homePage() {
ModelAndView model = new ModelAndView();
model.setViewName("homePage");
return model;
}
@RequestMapping(value = "/loginPage", method = RequestMethod.GET)
public ModelAndView loginPage(@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 Credentials provided.");
}
if (logout != null) {
model.addObject("message", "Logged out from JournalDEV successfully.");
}
model.setViewName("loginPage");
return model;
}
}
Code Explanation:- We have defined three methods in “LoginController” to handle three different kinds of Client Requests
package com.journaldev.spring.secuity.config;
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 LoginSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder authenticationMgr) throws Exception {
authenticationMgr.inMemoryAuthentication()
.withUser("journaldev")
.password("jd@123")
.authorities("ROLE_USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/homePage").access("hasRole('ROLE_USER')")
.and()
.formLogin().loginPage("/loginPage")
.defaultSuccessUrl("/homePage")
.failureUrl("/loginPage?error")
.usernameParameter("username").passwordParameter("password")
.and()
.logout().logoutSuccessUrl("/loginPage?logout");
}
}
Code Explanation:- We have defined two methods in “LoginSecurityConfig” to store and manage User Credentials and take care of Login and Logout Security features.
.antMatchers("/homePage").access("hasRole('ROLE_USER')")
If we remove access(“hasRole(‘ROLE_USER’)”) method call, then we can access this page without login to our application.13. We have configured login and logout features using formLogin() and logout() methods.
package com.journaldev.spring.secuity.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
@EnableWebMvc
@Configuration
@ComponentScan({ "com.journaldev.spring.*" })
@Import(value = { LoginSecurityConfig.class })
public class LoginApplicationConfig {
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
Code Explanation:- We use “LoginApplicationConfig” class to define Spring MVC View Resolvers to avoid writing “web.xml” file.
package com.journaldev.spring.secuity.config.core;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {
}
“SpringSecurityInitializer” is used to register the DelegatingFilterProxy
to use the springSecurityFilterChain. It avoids writing Filters configuration in web.xml file.- Initialize Spring MVC Application
“SpringMVCWebAppInitializer” class is used to initialize “DispatcherServlet” without web.xml file in a Annotation based configuration. SpringMVCWebAppInitializer.java
package com.journaldev.spring.secuity.config.core;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import com.journaldev.spring.secuity.config.LoginApplicationConfig;
public class SpringMVCWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { LoginApplicationConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
NOTE:-
<h3>Welcome to JournalDEV Tutorials</h3>
<a href="${pageContext.request.contextPath}/loginPage">Login to Journal</a>
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<html>
<body onload='document.loginForm.username.focus();'>
<h3>JournalDEV Tutorials</h3>
<c:if test="${not empty error}"><div>${error}</div></c:if>
<c:if test="${not empty message}"><div>${message}</div></c:if>
<form name='login' action="<c:url value='/loginPage' />" method='POST'>
<table>
<tr>
<td>UserName:</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>
</body>
</html>
<%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<h3>Welcome to JournalDEV Tutorials</h3>
<ul>
<li>Java 8 tutorial</li>
<li>Spring tutorial</li>
<li>Gradle tutorial</li>
<li>BigData tutorial</li>
</ul>
<c:url value="/logout" var="logoutUrl" />
<form id="logout" action="${logoutUrl}" method="post" >
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
<c:if test="${pageContext.request.userPrincipal.name != null}">
<a href="javascript:document.getElementById('logout').submit()">Logout</a>
</c:if>
To run this Spring Web Application, we need any Web Container which supports Spring 4 and Java 8 Environments With Servlet 3.1.0 Container.
NOTE:- If we observe this example, we are not using the web.xml file right. As it is a Web Application, Maven searches for web.xml file and raises some errors if it does not find in the application. That’s to avoid Maven related issues, we need to configure “<failOnMissingWebXml>” flag in pom.xml file. That’s it all about Spring 4 Security Module Simple Example. We will develop some more real-time useful examples in my coming posts like Managing Roles, Remember-Me Feature, WebSocket Security, and more. Please drop me a comment if you like my post or have any issues/suggestions.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
Thank so much ! Keep doing
- vu
Hi Pankaj, Thanks for writing this article, This is a very simple and acute example to understand the Spring security I followed your steps to implement Spring security in one of my existing tutorial project. But I am getting some issues while going to deploy .war file. Could you please check the issue, what it is exactly. I googled it but I couldn’t find the expected result. Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method ‘springSecurityFilterChain’ threw exception; nested exception is java.lang.NoSuchMethodError: org.springframework.util.Assert.isTrue(ZLjava/util/function/Supplier;)V
- Devdyuti singh
Thank You so much. very proper and step by step description gave. Please we want managing different user roles example
- Akash
Is it possible to use hashed password instead of plain text in LoginSecurityConfig class, so no one easily guess it?
- Sumit Sood
Please help! I am getting following problem: Nov 20, 2017 4:19:02 PM org.springframework.web.servlet.PageNotFound noHandlerFound WARNING: No mapping found for HTTP request with URI [/SpringMVCSecruityMavenApp/${pageContext.request.contextPath}/loginPage] in DispatcherServlet with name ‘dispatcher’
- Rajesh Gupta
I am trying to implement Spring Security in my existing Spring MVC project . I have designed my flow like when my application first loads then it goes to “Index.jsp” as below: @RequestMapping(value =“/” , method = RequestMethod.GET) public ModelAndView Index() { System.out.println(“Index”); ModelAndView form = new ModelAndView(“Index”); return form; } And my Index.jsp contains two buttons 1) SignUp and 2) Login . Both this button opens their respective “Modal” on same page . And submits a post request as below : @RequestMapping(value = “/login”, method = RequestMethod.POST) public ModelAndView Login(@RequestParam Map reqvar) { //… //… } @RequestMapping(value = “/signup”, method = RequestMethod.POST) public ModelAndView SignUp(@RequestParam Map reqvar) { //… //… } Now I want to implement Spring Security . How to implement ?? I want some thing that once I submit form from Model for login using {context}/login then Spring should authenticate me for provided userid and password. . So what should I write in " protected void configure(HttpSecurity http) throws Exception {" method ?? As of now I have written some thing like below , but it is not working : @Configuration @EnableWebSecurity public class SpringSecurity extends WebSecurityConfigurerAdapter { public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception{ auth.inMemoryAuthentication().withUser(“rishavraj3@jellyfish.com”) .password(“123456”).authorities(“ROLE_USER”); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); // disabled csrf as of now for simplicity . http.authorizeRequests().antMatchers(“/login”). access(“hasRole(‘ROLE_USER’)”).and().formLogin().loginPage(“/index”); } }
- RISHAV
SIr getting this error The absolute uri: https://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application
- shoaib ali
Hi Sir, After added correct credentials, getting below error…i have homePage.jsp in place. HTTP Status 404 - /SpringMVCSecruityMavenApp/WEB-INF/views/homePage.jsp -------------------------------------------------------------------------------- type Status report message /SpringMVCSecruityMavenApp/WEB-INF/views/homePage.jsp description The requested resource is not available. -------------------------------------------------------------------------------- Apache Tomcat/7.0.81 Regards
- Venkata Reddy
Hi, Why is it that when after I login I can still access the login page and it doesn’t redirect to the homePage
- Mel
Getting 404 error WARNING: No mapping found for HTTP request with URI [/ex/welcome] in DispatcherServlet with name ‘dispatcher’
- Pash