Main Tutorials

Spring Security Custom Login Form Example

By default, if no login form is specified, Spring Security will create a default login form automatically. Please refer to this – Spring Security hello world example.

In this tutorial, we will show you how to create a custom login form for Spring Security (XML example).

Technologies used :

  1. Spring 3.2.8.RELEASE
  2. Spring Security 3.2.3.RELEASE
  3. Eclipse 4.2
  4. JDK 1.6
  5. Maven 3
Note
In this example, previous Spring Security hello world example will be reused, enhance it to support a custom login form.

1. Project Demo

2. Directory Structure

Review the final directory structure of this tutorial.

spring-security-custom-login-xml-directory

3. Spring Security Configuration

Defined your custom login form in Spring XML file. See explanation below :

  1. login-page=”/login” – The page to display the custom login form
  2. authentication-failure-url=”/login?error” – If authentication failed, forward to page /login?error
  3. logout-success-url=”/login?logout” – If logout successful, forward to view /logout
  4. username-parameter=”username” – The name of the request which contains the “username”. In HTML, this is the name of the input text.
  5. <csrf/> – Enable the Cross Site Request Forgery (CSRF) protection, refer to this link. In XML, by default, CSRF protection is disabled.

Normally, we don’t involve in the authentication like login or logout processing, let Spring handle it, we just handle the successful or failed page to display.

spring-security.xml

<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-3.0.xsd
	http://www.springframework.org/schema/security
	http://www.springframework.org/schema/security/spring-security-3.2.xsd">

	<http auto-config="true">
		<intercept-url pattern="/admin**" access="ROLE_USER" />
		<form-login 
		    login-page="/login" 
		    default-target-url="/welcome" 
			authentication-failure-url="/login?error" 
			username-parameter="username"
			password-parameter="password" />
		<logout logout-success-url="/login?logout" />
		<!-- enable csrf protection -->
		<csrf/>
	</http>

	<authentication-manager>
		<authentication-provider>
		  <user-service>
			<user name="mkyong" password="123456" authorities="ROLE_USER" />
		  </user-service>
		</authentication-provider>
	</authentication-manager>

</beans:beans>

In above congratulation, the /admin and sub-folders of it are all password protected.

Cross Site Request Forgery (CSRF) Protection
If CSRF is enabled, you have to include a _csrf.token in the page you want to login or logout. Refer to below login.jsp and admin.jsp (logout form). Otherwise, both login and logout function will be failed.
Password in clear-text?
A pretty bad idea, you should always hash the password with SHA algorithm, this tutorial show you how – Spring Security password hashing example.

4. Custom Login Form

A custom login form to match above (step 3) Spring Security congratulation. It should be self-explanatory.

login.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>Login Page</title>
<style>
.error {
	padding: 15px;
	margin-bottom: 20px;
	border: 1px solid transparent;
	border-radius: 4px;
	color: #a94442;
	background-color: #f2dede;
	border-color: #ebccd1;
}

.msg {
	padding: 15px;
	margin-bottom: 20px;
	border: 1px solid transparent;
	border-radius: 4px;
	color: #31708f;
	background-color: #d9edf7;
	border-color: #bce8f1;
}

#login-box {
	width: 300px;
	padding: 20px;
	margin: 100px auto;
	background: #fff;
	-webkit-border-radius: 2px;
	-moz-border-radius: 2px;
	border: 1px solid #000;
}
</style>
</head>
<body onload='document.loginForm.username.focus();'>

	<h1>Spring Security Custom Login Form (XML)</h1>

	<div id="login-box">

		<h2>Login with Username and Password</h2>

		<c:if test="${not empty error}">
			<div class="error">${error}</div>
		</c:if>
		<c:if test="${not empty msg}">
			<div class="msg">${msg}</div>
		</c:if>

		<form name='loginForm'
		  action="<c:url value='j_spring_security_check' />" method='POST'>

		  <table>
			<tr>
				<td>User:</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>
	</div>

</body>
</html>

And the other two JSP pages, btw admin.jsp is password protected by Spring Security.

hello.jsp

<%@page session="false"%>
<html>
<body>
	<h1>Title : ${title}</h1>	
	<h1>Message : ${message}</h1>	
</body>
</html>
admin.jsp + logout

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@page session="true"%>
<html>
<body>
	<h1>Title : ${title}</h1>
	<h1>Message : ${message}</h1>

	<c:url value="/j_spring_security_logout" var="logoutUrl" />

	<!-- csrt for log out-->
	<form action="${logoutUrl}" method="post" id="logoutForm">
	  <input type="hidden" 
		name="${_csrf.parameterName}"
		value="${_csrf.token}" />
	</form>
	
	<script>
		function formSubmit() {
			document.getElementById("logoutForm").submit();
		}
	</script>

	<c:if test="${pageContext.request.userPrincipal.name != null}">
		<h2>
			Welcome : ${pageContext.request.userPrincipal.name} | <a
				href="javascript:formSubmit()"> Logout</a>
		</h2>
	</c:if>

</body>
</html>

5. Spring MVC Controller

A simple controller.

HelloController.java

package com.mkyong.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 HelloController {

	@RequestMapping(value = { "/", "/welcome**" }, method = RequestMethod.GET)
	public ModelAndView welcomePage() {

		ModelAndView model = new ModelAndView();
		model.addObject("title", "Spring Security Custom Login Form");
		model.addObject("message", "This is welcome page!");
		model.setViewName("hello");
		return model;

	}

	@RequestMapping(value = "/admin**", method = RequestMethod.GET)
	public ModelAndView adminPage() {

		ModelAndView model = new ModelAndView();
		model.addObject("title", "Spring Security Custom Login Form");
		model.addObject("message", "This is protected page!");
		model.setViewName("admin");

		return model;

	}

	//Spring Security see this :
	@RequestMapping(value = "/login", method = RequestMethod.GET)
	public ModelAndView login(
		@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 username and password!");
		}

		if (logout != null) {
			model.addObject("msg", "You've been logged out successfully.");
		}
		model.setViewName("login");

		return model;

	}

}

6. Demo

6.1. Welcome Page – http://localhost:8080/spring-security-loginform-xml/

spring-security-custom-login-xml-welcome

6.2 Try to access /admin page, Spring Security will intercept the request and redirect to /login, and your custom login form is displayed.

spring-security-custom-login-xml-login

6.3. If username and password is incorrect, error messages will be displayed, and Spring will redirect to this URL /login?error.

spring-security-custom-login-xml-error

6.4. If username and password are correct, Spring will redirect to the original requested URL and display the page.

spring-security-custom-login-xml-admin

6.5. Try to log out, it will redirect to /login?logout page.

spring-security-custom-login-xml-logout

Download Source Code

References

  1. Spring Security Hello World XML Example
  2. Creating a Custom Login Form
  3. Spring Security 3.2.0.RC1 Highlights: CSRF Protection

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
94 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
vishnupriya
7 years ago

hi i have tried your example i am getting no handler for j_spring_security_check…

rajesh
5 years ago
Reply to  vishnupriya

no need j_spring_security_check interceptor internally provided by spring security. make sure about your username and password input field has the same parameter as defined in SecurityConfig class .

MUKESH THAKUR
7 years ago
Reply to  vishnupriya

hi
vishnupriya

how to create login page in spring mvc where 10 username or password is hardcoded using map interface

please solve this problem

Rishi
4 years ago

can you share password less authentication using Spring MVC and Spring Security

El Kn
5 years ago

Where is the documentation for the XML descriptors?

harry potter
6 years ago

Hi, How r u getting the user context in the above example ?

ABC
6 years ago

No program run here. Are you fooling people?

Mahesh S
7 years ago

Hi.. I have done a social app what type of security I can give for that

Rocky
8 years ago

Mkyong thank you for the tutorial, I gave you +20 rep. in stackoverflow, now your reputation moves up to 1011 😉

Leang Socheat
8 years ago

what is a *?. for example admin**, what does it mean?

Htet Naing Aung
3 years ago
Reply to  Leang Socheat
  • meaning of * is other character can add behind of “admin”
  • Example: /adminLogin
giorgio amato
8 years ago

Please note that like this it doesn’t work, because you need also processing url in the spring-security.xml, like the following:

with this you will get correct feedback information about login attempt

Yasin Kasap
8 years ago

Hi Mknyong,

I wanna call you “sensei”

Thanks

agung wijaya
8 years ago

it appears that is not supported in spring security 3.1. how do I enable csrf in that version?

Polyk
8 years ago

In the login method of the controller, the user is redirected again to the login page even if there is no error —> loop !
How can it go back to the admin page ?

Polyk
8 years ago
Reply to  Polyk

Solved . I haven’t used the wright username-parameter

Anshul
8 years ago

Hi.. The project s awesome but whenever i’m adding filter tags to my web.xml it is giving me resource unavailable error after that. can anyone tell me why it is happening??

Prasanna
9 years ago

I Am getting now this error:

java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener

Teejay
9 years ago

Hi, Can I use Spring MVC Form Tags (eg, ) with Spring Security functionality together? I noticed everyone uses standard html form tags. If it’s possible, what would be the parts to care about? Thanks a lot in advance!!

Jack Parker
9 years ago

If I want to implement this into an existing project. Let’s say without the welcome page redirect, and the page goes straight to the login, and then to the index. jsp page for my project how would I go about that?

I’ve tried setting it up according to the instructions here, and on another site, but I keep getting a 404 error anytime I make any sort of change to the web.xml

karthi
9 years ago

Hi
This post is awesome. I uploaded ur project by choosing Import-> Existing Maven Project . What shld I choose if i do it by my own. ie whether to choose File-> New ( A Maven Project or a Spring Project or Simple Spring Maven or Simple Spring Web Maven

Nicki
9 years ago

Hi ,

My project name is Formhandling .i tried to use spring security .i am facing below error:
WARNING: No mapping found for HTTP request with URI [/FormHandling/kik] in DispatcherServlet with name ‘FormHandling’
Jan 19, 2015 11:17:07 PM org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping found for HTTP request with URI [/FormHandling/] in DispatcherServlet with name ‘FormHandling’
plzz hlp

konstantinh
9 years ago

mkyong that is a good post , however could you please elaborate on something i.e.your hello controller has only get methods, where is the HTTP post beeing done? One thing i do not understand is why this constelation is working at all, if the HTTP POST where the username and the password are supposed to be recieveid is not beeing processed from this code, or is there any magic behind this? I would really appreciate any feedback regarding this question. The reason i am asking this question is because i would like to use your example but work on my custome login controller, for example what would your login controller look like if you had not just user name and password but additional parameters such as certificate , or what if you were about to authenticate SRP (Secure Remote Password protocol) application

Rajesh
9 years ago

i am getting two errors to run the program.

1.java.lang.NoSuchMethodError: org.springframework.web.context.support.XmlWebApplicationContext.getEnvironment()Lorg/springframework/core/env/ConfigurableEnvironment;

2.java.lang.IllegalStateException: LifecycleProcessor not initialized – call ‘refresh’ before invoking lifecycle methods via the context: Root WebApplicationContext: startup date [Sat Sep 27 17:45:41 IST 2014]; root of context hierarchy

h47
9 years ago

Hi Mkyong : am rookie to springFw i got required output as i coded as in above example of yours; But a Big ” ” ” ” Disappointing ” factor is that after i logout and i click on browser ” Back button ” then it shows previous admin page, why is this happing same problem is occurs and not solved when i write Basic JSP AND SERVLET web app, any suggestions mky. thank for this tutorial…

Sonu Kumar
9 years ago

Hello “Mr. Mkyong” all is good. but could you please provide the .xml files so that the freshers are also can understand. if it’s possible then please provide.

Sonu Kumar
9 years ago

in STS, when press login button…
WARN : org.springframework.web.servlet.PageNotFound – No mapping found for HTTP request with URI [/lead/] in DispatcherServlet with name ‘appServlet’

Surendran Duraisamy
9 years ago

Following are the problems I faced. Hope this would be helpful for other.

1. class loader issue.
Solution: include spring jar in the lib folder of your war
2. EL expressions not evaluated
Solution: use following tag for

akshay
9 years ago

Sir,
Can you please show me how save and retrieve an image from sql in spring.

Roberto Massimi
10 years ago

Nice tutorial.
It’s work for me but I don’t load a static resource.
I’ve copied header.png in srcmainwebapprisorse.
in hello.jsp I put
<img src='’ alt=”” id=”logo”/>
but i received this error:
Failed to load resource: the server responded with a status of 404 (Not Found)
How to load static resource? I read from web, ma I don’t understand the solution.
You can help me?

*sorry for a little my english
Roberto

shggy
10 years ago

Nice tutorial
But I am getting problem,
I am getting login page twice and then it gets logged in
Why?

lolo
10 years ago

How can we do to Junit test for this

1-login-page=”/login” – The login form will be “/login”
2-default-target-url=”/welcome” – If authentication success, forward to “/welcome”
3-authentication-failure-url=”/loginfailed” – If authentication failed, forward to “/loginfailed”
4-logout-success-url=”/logout” – If logout , forward to “/logout”

Manas
10 years ago

Good Post but I am weak in Java
Here find login form in PHP
http://www.discussdesk.com/download-login-form-in-PHP-and-mysql.htm

kon
10 years ago
Reply to  Manas

for what?

Vicky
10 years ago

One strange behavior that I noticed is, once you are at url http://localhost:8080/SpringMVC/login

and provide the incorrect url then url should be changed to http://localhost:8080/SpringMVC/loginfailed but it is not! It is at /login only. What can be the reason?

errikos
10 years ago
Reply to  Vicky

Are you sure you have the @RequestMapping annotation in the loginError method?