Spring Security Custom Error Message

In this tutorial , we will discuss about Custom Error Message in Spring Security instead of default message of Spring Security.

Spring Security have predefined error message, which appears when authentication failed. The predefined error message is given below
Your login attempt was not successful, try again.

Reason: Bad credentials

You can change this predefined failed authentication error message. For example you want see the following message instead of the default message as follows.

Your login attempt was not successful, try again.

Invalid username or password
You need to add the following change in the sdnext-servlet.xml :
<bean id="messageSource"
        class="org.springframework.context.support.ResourceBundleMessageSource">
      <property name="basenames">
         <list>
               <value>message_en</value>
         </list>
      </property>
</bean>

Spring Security stored messages in "messages.properties" inside "spring-security-core.jar", see figure below :

To override it, find which key generate what error message in spring security message.properties file, and redefine it with your own properties file.

message_en.properties
AbstractUserDetailsAuthenticationProvider.badCredentials=Invalid username or password

Please look the previous example "Spring Security Login Form Example" for this and go ahead.

In the below example, we will going to change it with custom error message :

The project hierarchy and jar file used is given below :


Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

 <servlet>
  <servlet-name>sdnext</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
 </servlet>

 <servlet-mapping>
  <servlet-name>sdnext</servlet-name>
  <url-pattern>/</url-pattern>
 </servlet-mapping>
 <listener>
  <listener-class>
                  org.springframework.web.context.ContextLoaderListener
        </listener-class>
 </listener>
 
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
   /WEB-INF/sdnext-*.xml,
  </param-value>
 </context-param>
 
 <welcome-file-list>
  <welcome-file>index</welcome-file>
 </welcome-file-list>
 
 <!-- Spring Security -->
 <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>
 
</web-app>

sdnext-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:security="http://www.springframework.org/schema/security"
       xmlns:p="http://www.springframework.org/schema/p" 
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/security
                           http://www.springframework.org/schema/security/spring-security-3.1.xsd">

   <security:http auto-config="true">
  <security:intercept-url pattern="/index*" access="ROLE_USER" />
  <security:form-login login-page="/login" default-target-url="/index"
   authentication-failure-url="/fail2login" />
  <security:logout logout-success-url="/logout" />
 </security:http>

    <security:authentication-manager>
   <security:authentication-provider>
     <security:user-service>
   <security:user name="dineshonjava" password="sweety" authorities="ROLE_USER" />
     </security:user-service>
   </security:authentication-provider>
 </security:authentication-manager>

</beans>

sdnext-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

 <context:component-scan base-package="com.dineshonjava.security" />

 <bean id="jspViewResolver"
  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="viewClass"
   value="org.springframework.web.servlet.view.JstlView" />
  <property name="prefix" value="/WEB-INF/views/" />
  <property name="suffix" value=".jsp" />
 </bean>
 
 <bean id="messageSource"
        class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames">
           <list>
                 <value>message_en</value>
           </list>
        </property>
 </bean>
 
</beans>

LoginSecurityController.java

package com.dineshonjava.security.controller;

import java.security.Principal;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * @author Dinesh Rajput
 *
 */
@Controller
public class LoginSecurityController {
 
 @RequestMapping(value="/index", method = RequestMethod.GET)
 public String executeSecurity(ModelMap model, Principal principal ) {
 
  String name = principal.getName();
  model.addAttribute("author", name);
  model.addAttribute("message", "Welcome To Login Form Based Spring Security Example!!!");
  return "welcome";
 
 }
 
 @RequestMapping(value="/login", method = RequestMethod.GET)
 public String login(ModelMap model) {
 
  return "login";
 
 }
 
 @RequestMapping(value="/fail2login", method = RequestMethod.GET)
 public String loginerror(ModelMap model) {
 
  model.addAttribute("error", "true");
  return "login";
 
 }
 
 @RequestMapping(value="/logout", method = RequestMethod.GET)
 public String logout(ModelMap model) {
 
  return "login";
 
 }
}

login.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>Login Page For Security</title>
<style>
.errorblock {
 color: #ff0000;
 background-color: #ffEEEE;
 border: 3px solid #ff0000;
 padding: 8px;
 margin: 16px;
}
</style>
</head>
<body onload='document.f.j_username.focus();'>
 <h3>Login with Username and Password (Custom Login Page with custom error message)</h3>
 
 <c:if test="${not empty error}">
  <div class="errorblock">
   Your login attempt was not successful, try again.<br /> Caused :
   ${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}
  </div>
 </c:if>
 
 <form name='f' action="<c:url value='j_spring_security_check' />"
  method='POST'>
 
  <table>
   <tr>
    <td>User:</td>
    <td><input type='text' name='j_username' value=''>
    </td>
   </tr>
   <tr>
    <td>Password:</td>
    <td><input type='password' name='j_password' />
    </td>
   </tr>
   <tr>
    <td colspan='2'><input name="submit" type="submit"
     value="submit" />
    </td>
   </tr>
   <tr>
    <td colspan='2'><input name="reset" type="reset" />
    </td>
   </tr>
  </table>
 
 </form>
</body>
</html>

Running the example

Export the example as war and deploy it Tomcat 7 server. While browsing the project you will get the following screen for loging:

Access URL "http://localhost:8080/sdnext/index", Spring will redirect to your custom login form.
URL : http://localhost:8080/sdnext/login

If username/password is wrong, authentication failed, display custom error messages.

URL : http://localhost:8080/sdnext/fail2login

 

Download Source Code-
SpringSecurityCustomErrorMsg.zip


References-
http://www.dineshonjava.com/2013/02/spring-security-form-based-login-example.html
Spring Security
Spring Security documentation


                             <<previous<<             || index  ||         >>next>>



No comments:

Post a Comment