In this tutorial we will discuss same previous example of custom login form for authentication but difference is that only we using database for username and password instead of reading from XML file.
Required Tools used for this Application:
- Spring MVC 3.0.1
- Spring Security 3.1.0
- STS 2.8.1.RELEASE
- Tomcat 7
- Jdk 1.7
- MySQL Database
To understand this application you have some prior knowledge about the Spring MVC web application.
Spring Security Login Form Using Database
Step 1: Please download the following more jars for Spring Security Lib from its official site.
To get started with the implementation, following jars need to be present in the class path of the project.
- spring-security-acl-3.1.3.RELEASE.jar
- spring-security-aspects-3.1.3.RELEASE.jar
- spring-security-cas-3.1.3.RELEASE.jar
- spring-security-config-3.1.3.RELEASE.jar
- spring-security-core-3.1.3.RELEASE.jar
- spring-security-crypto-3.1.3.RELEASE.jar
- spring-security-ldap-3.1.3.RELEASE.jar
- spring-security-openid-3.1.3.RELEASE.jar
- spring-security-remoting-3.1.3.RELEASE.jar
- spring-security-taglibs-3.1.3.RELEASE.jar
- spring-security-web-3.1.3.RELEASE.jar
Step 2: Create the project “SpringSecurityLoginDatabase” with packages“com.dineshonjava.security.controller” and create the “LoginController.java” file in this package.
Step 3: Some more folders also create on the “WEB-INF” folder with name libs, views for jars and jsp files respectively. Two files “sdnext-servlet.xml” and “sdnext-security.xml” are created on the “WEB-INF” folder.
Namespace Configuration:
The namespace configuration of the spring provides lot of shortcuts that hides much of the complexity of the framework. To start with this configuration, define a security filter in web.xml as shown below:
Step 4: Configuring web.xml for Spring Security
<?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>
In the above configuration, DelegatingFilterProxy delegates the control to a filter implementation which is defined as a bean named springSecurityFilterChain. This bean is an infrastructure internal bean to handle namespace configurations. Once this configuration is done, all the incoming requests enter the spring framework for security checks.
Security Configuration:
The security configuration is done in XML file and can have any name such as sdnext-security.xml. This file needs to be loaded explicitly from web.xml. This is done by adding ContextLoadListener. The following lines needs to be added before security filter definition in web.xml.
Step 5: Spring Securing Configuration file (sdnext-security.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:jdbc-user-service data-source-ref="dataSource" users-by-username-query="select username, password, active from users where username=?" authorities-by-username-query="select us.username, ur.authority from users us, user_roles ur where us.user_id = ur.user_id and us.username =? " /> </security:authentication-provider> </security:authentication-manager> </beans>
This configuration is done to enable form-login authentication model where the login page is login.jsp. Note that in the intercept tag, pattern for /index* is given and access rule is defined as ROLE_USER. That means /index* is redirect to /login to checked for security, which makes sense as login.jsp is the starting point from where the user is authenticated.
The tag <security:authentication-manager> processes the authentication information; <security:authentication-provider> defines the credential information and the roles given to each user (authentication information).
Step 6: Spring Configuration File (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:property-placeholder location="classpath:resources/database.properties" /> <context:component-scan base-package="com.dineshonjava.security" /> <tx:annotation-driven transaction-manager="hibernateTransactionManager"/> <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="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${database.driver}" /> <property name="url" value="${database.url}" /> <property name="username" value="${database.user}" /> <property name="password" value="${database.password}" /> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> </props> </property> </bean> </beans>
Step 7: Creating LoginController class (LoginController.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 LoginController { @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"; } }
Creating database.properties
database.driver=com.mysql.jdbc.Driver database.url=jdbc:mysql://localhost:3306/DAVDB database.user=root database.password=root hibernate.dialect=org.hibernate.dialect.MySQLDialect hibernate.show_sql=true hibernate.hbm2ddl.auto=update
JSP Views-
In custom login form, you have to follow Spring Security standard name :
1. j_spring_security_check – Login service
2. j_spring_security_logout – Logout service
3. j_username – Username
4. j_password – Password
Step 8: Creating welcome page (welcome.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> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>WELCOME TO SECURE AREA</title> </head> <body> <h1>Message : ${message}</h1> <h1>Author : ${author}</h1> <a href='<c:url value="/j_spring_security_logout" />' > Logout</a> </body> </html>
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)</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>
Step 9: Create an database “DAVDB” and two tables “USERS” and other “USER_ROLES” for Spring Security for our application as follows.
USERS Table
CREATE TABLE `users` ( `USER_ID` int(10) unsigned NOT NULL, `USERNAME` varchar(40) NOT NULL, `PASSWORD` varchar(40) NOT NULL, `ACTIVE` tinyint(1) NOT NULL, PRIMARY KEY (`USER_ID`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1
USER_ROLES table
Create Table CREATE TABLE `user_roles` ( `USER_ROLE_ID` int(10) unsigned NOT NULL, `USER_ID` int(10) unsigned NOT NULL, `AUTHORITY` varchar(45) NOT NULL, PRIMARY KEY (`USER_ROLE_ID`), KEY `FK_user_roles` (`USER_ID`), CONSTRAINT `FK_user_roles` FOREIGN KEY (`USER_ID`) REFERENCES `users` (`USER_ID`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1
INSERT INTO `DAVDB`.`user_roles` (`USER_ROLE_ID`, `USER_ID`, `AUTHORITY` ) VALUES ('1', '1', 'ROLE_USER' );
INSERT INTO `DAVDB`.`users` (`USER_ID`, `USERNAME`, `PASSWORD`, `ACTIVE` ) VALUES ('1', 'dineshonjava', 'sweety', '1' );
Step 10: 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 login:
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
If username/password is correct, authentication success, display requested page.
URL : http://localhost:8080/sdnext/index
If username/password is correct, authentication success, display requested page.
on requested page click on Logout link.
URL : http://localhost:8080/sdnext/logout
Download Source Code + Libs
SpringSecurityLoginDatabase.zip
References-
https://www.dineshonjava.com/spring-security-form-based-login-example/
Spring Security
Spring Security documentation
- Spring Security Interview Questions and Answers
- Spring Security Java Based Configuration with Example
- Spring Security XML Namespace Configuration Example
- Spring Security XML Based Hello World Example
- Spring Security form-based login example
- Spring Security Login Form Based Example Using Database
- Spring Security Authentication Example Using HTTP Basic
- Spring Security Authorized Access Control Example
- Spring Security Customized Access Denied Page
- Spring Security Custom Error Message
- Spring Security Logout Example
- Spring Security Fetch Logged in Username
- Spring Security Password Hashing
Hai Dinesh
How to create tables in sql
you gives my sql tables in that [Active tinyint(1)] this type how to take in sql plz reply me
Hi Ravi,
Which database you are using?
It is tested on MySQL database.
hello,
i have some error, can u help me?
ERROR: org.springframework.web.context.ContextLoader – Context initialization failed
java.lang.NoClassDefFoundError: org/springframework/expression/BeanResolver
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.lang.Class.getDeclaredMethods(Unknown Source)
at org.springframework.core.type.StandardAnnotationMetadata.hasAnnotatedMethods(StandardAnnotationMetadata.java:136)
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.checkConfigurationClassCandidate(ConfigurationClassBeanDefinitionReader.java:320)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:157)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:132)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:584)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:405)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:272)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:196)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4791)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5285)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: org.springframework.expression.BeanResolver
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1714)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
Hi Subbiah.G,
You are missing some jars files please make sure are you adding spring-bean.jar like jars..
Thanks,
Dinesh
Hi Dinesh,
I have got HTTP Status 404 – /SpringSecurityLoginDatabase/ error while running application.Could you please help on this.
This is a very good tutorial,but I have a problem I want to run the project on the server showme error http 404, I download de project and imported to eclipse and also added all jars in build path.please help on this asap.
Thanks,
Ashish Gupta
hi, dinesh
me also got the same error 404 actually i done all the steps and i configured build path even though i got the 404 can you please help me
Hi Ashish,
Please update context root of your application then redeploy again.
Thanks,
Dinesh
Are changing context root of application.
http://localhost:8080/sdnext/login
HI Dinesh, I want to implement Spring Security with Hibernate ( login and logout for users) using only Annotations approach.
Can you shed some knowledge on this.
Thanks,
San
sir please make in youtube videos in spring tutorials
Message /sdnext/
Description The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
how to solve that problem
how to be configured in web .xml file