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.
Excelent article on Spring4 Security Example. Plz post some advanced examples to demo Spring4 Features.
- Ramu P
Thank you for this nice example, Rambabu.It works )
- Yuriy I.
Very good tutorial. Im seaching for similar exmple in net for last few days. Thank u so much for your effort. Keep up good work
- Bibhu
Excellent tutorial , but we need some more in depth explanation , so that we can become more strong in spring !!! Thanks & Regards, Krishna Arigela.
- krishna Arigela
Hi, Please write a SPRING4 SECURITY+ HIBERNATE4+ JSF + MYSQL + SPRING4 TUTORIAL. You could follow this link https://marco-ng.blogspot.in/2014/02/primefaces-jsf2-spring-security-spring.html Thanks Raichand
- Raichand Ray
Muchas gracias. Es el primer tutorial que me ha funcionado a la primera y además lo he entendido. Felicidades.
- arbil74
Its showing 404 error.Please help me with ASAP. thanks.
- sirireddy
actually there’s a misspelling on welcomPage.jsp, missing “e” there.
- Jeffery
Thank you so much for good catch. Updated that one.
- Rambabu Posa
thank you csrf hidden parameter in the form post helped!
- M
Brilliant, something i was looking for in spring security with spring 4 setup. Thanks a lot. Works like a charm.
- Manish
Actually really interesting. Thank you very much sir…
- Iroshan
how come the controller methods are get and the form actions are post?
- sandy
thank you. very helpful especially about logout link and form
- seyfer
Thanks for your post but is it work for multiple tab authentication?
- Shakib Ahmed
Very helpfull, thankyou can you put the link were you explain remenmbre me feature?
- marouane
It is a good article. But I am getting this exception. HTTP Status 403 - Invalid CSRF Token ‘null’ was found on the request parameter ‘_csrf’ or header ‘X-CSRF-TOKEN’. could any one help me to solve this issue?
- prasanna wagh
Check your JSP as you have mentioned EL ignored as fasle like.
- Jesudasan M
Can you please elaborate, sir? I’m having the same exception too and can’t seem to fix it. Thanks!
- Hea
add it in jsp
- Rahul
org.springframework.web.servlet.PageNotFound handleHttpRequestMethodNotSupported ADVERTENCIA: Request method ‘POST’ not supported in weblogic 12
- der
Above Same exception me too… in Tomcat 8.x when i click on login button. but for avoid that exception i modified on “loginPage.jsp” by method=‘GET’. then no exception but its calling same login page every time. Please anyone can suggest me how can i enter in “HomePage”
- Yogesh
Sir can you please provide us source code.
- piya
+1
- ABC
i am facing some problem,pls help me… Error 403–Forbidden From RFC 2068 Hypertext Transfer Protocol – HTTP/1.1: 10.4.4 403 Forbidden The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable.
- Purushottam
No matter what I try this example doesn’t work AT ALL. I keep getting the below error, <> The only difference being in the pom.xml with Eclipse plugin added as below, And oh yes my artifactId is different. maven-eclipse-plugin 2.9 org.springframework.ide.eclipse.core.springnature org.springframework.ide.eclipse.core.springbuilder true true
- VedVrat
Hi , I am getting below error after clicking submit button . i have followed same code which have provided in your blog . Can you please correct me if i miss some configuration .
- lakshmipriya
Excellent tutorial Sir , but I need some more explanation of its flow, So that it will be more easy to become more strong in spring !!! I have a bit confusion on loginPage.jsp and LoginController.java. In loginPage.jsp the method is mentioned as “POST” but in loginPage() of LoginController.java it mentioned as "GET " So is there any mismatch? Please explain… Thanks, Pranjay
- pranjay Kumar
If I’m right, LoginController just controls the flow to open up loginPage view, doesn’t have anything to do with authentication. Just loads the view when “/loginPage” is loaded in URL. So it should be GET. The authentication takes place in LoginSecurityConfig. The authentication API configured here should have POST… In loginPage.jsp, changing the api name to ‘appLogin’ and adding ‘appLogin’ as login processing url in LoginSecurityConfig did the trick. LoginPage.jsp: <form name=‘login’ action=“” method=‘POST’> LoginSecurityConfig.java: .formLogin().loginPage(“/loginPage”) .loginProcessingUrl(“/appLogin”) .defaultSuccessUrl(“/homePage”)
- SDJ
action should be /appLogin, I guess I missed it in my previous comment LoginPage.jsp:
- SDJ
when i submitted login credentials then i got response like HTTP Status 403 - Invalid CSRF Token ‘null’ was found on the request parameter ‘_csrf’ or header ‘X-CSRF-TOKEN’. how to solve this issue
- maheswara
you must disable csrf feature by http.csrf().disable()
- anhcacem
Excellent tutorial , but we need an exmple how to pass the username and password dynamically from database not static
- venkatesh
Getting 404 error WARNING: No mapping found for HTTP request with URI [/ex/welcome] in DispatcherServlet with name ‘dispatcher’
- Pash
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
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
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
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
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
Is it possible to use hashed password instead of plain text in LoginSecurityConfig class, so no one easily guess it?
- Sumit Sood
Thank You so much. very proper and step by step description gave. Please we want managing different user roles example
- Akash
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 so much ! Keep doing
- vu