Table of Contents
In this post, we will do authentication using database. We will use MySQL and hibernate for database authentication.
If you want to secure your spring web application , you just need to configure some files to make it happen using spring security. We will apply login security on hello world example, so when only authorised users will be able to access admin page.
Before going ahead, lets first configure database table in mysql which we will use for authentications.
Database setup:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
CREATEÂ TABLE users ( Â Â username VARCHAR(45) NOT NULL , Â Â password VARCHAR(45) NOT NULL , active TINYINT NOT NULL DEFAULT 1 , Â Â PRIMARY KEY (username)); Â Â Â CREATE TABLE user_roles ( Â Â user_role_id int(11) NOT NULL AUTO_INCREMENT, Â Â username varchar(45) NOT NULL, Â Â role varchar(45) NOT NULL, Â Â PRIMARY KEY (user_role_id), Â Â UNIQUE KEY unique_username_role (role,username), Â Â KEY fk_username_index (username), Â Â CONSTRAINT fk_username FOREIGN KEY (username) REFERENCES users (username)); Â INSERT INTO users(username,password,active) VALUES ('arpit','arpit', true); INSERT INTO users(username,password,active) VALUES ('john','john', true); Â INSERT INTO user_roles (username, role) VALUES ('arpit', 'ROLE_USER'); INSERT INTO user_roles (username, role) VALUES ('arpit', 'ROLE_ADMIN'); INSERT INTO user_roles (username, role) VALUES ('john', 'ROLE_USER'); |
Step 1:Â
Create Spring mvc hello world example named SpringSecurityDatabaseAuthenticationExample. It will create basic spring mvc application.
Step 2:Â
Add spring security, hibernate and mysql connector to pom.xml. You need to add following dependencies to the pom.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.arpit.java2blog</groupId> <artifactId>SpringSecurityDatabaseAuthenticationExample</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>SpringSecurityDatabaseAuthenticationExample Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!-- Spring Security --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>${security.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>${security.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>${security.version}</version> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> <scope>provided</scope> </dependency> <!-- Hibernate --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate.version}</version> </dependency> <!-- Apache Commons DBCP --> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <!-- Spring ORM --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> </dependencies> <build> <finalName>SpringSecurityHelloWorlExample</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>${jdk.version}</source> <target>${jdk.version}</target> </configuration> </plugin> </plugins> </build> <properties> <spring.version>4.2.1.RELEASE</spring.version> <security.version>4.0.3.RELEASE</security.version> <hibernate.version>4.3.5.Final</hibernate.version> <jdk.version>1.7</jdk.version> </properties> </project> |
Create Controller  and view
Step 3
Change controller class named “HelloWorldController.java” as below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
package org.arpit.java2blog.springmvc.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; import org.springframework.web.servlet.ModelAndView; @Controller public class HelloWorldController { @RequestMapping("/helloworld") public ModelAndView hello(ModelMap model,Principal principal) { String loggedInUserName=principal.getName(); return new ModelAndView("hello", "userName", loggedInUserName); } @RequestMapping("/admin") public ModelAndView helloAdmin(ModelMap model,Principal principal) { String loggedInUserName=principal.getName(); return new ModelAndView("admin", "userName", loggedInUserName); } @RequestMapping(value="/login", method = RequestMethod.GET) public String login(ModelMap model) { return "login"; } @RequestMapping(value="/loginError", method = RequestMethod.GET) public String loginError(ModelMap model) { model.addAttribute("error", "true"); return "login"; } // for 403 access denied page @RequestMapping(value = "/403", method = RequestMethod.GET) public ModelAndView accesssDenied(Principal user) { ModelAndView model = new ModelAndView(); if (user != null) { model.addObject("msg", "Hi " + user.getName() + ", You can not access this page!"); } else { model.addObject("msg", "You can not access this page!"); } model.setViewName("403"); return model; } } |
Here We have used Principal object to get current logged in username. It is set by Spring security framework.
Step 4:Â
Modify hello.jsp in /WEB-INF/pages folder
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Hello</title> </head> <body> ${message} <c:url value="/j_spring_security_logout" var="logoutUrl" /> <a href="${logoutUrl}">Log Out</a> </body> </html> |
Create login.jsp in /WEB-INF/pages folder
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <style type="text/css"> <%@include file="style.css" %> </style> <head> <title>Custom Login Page</title> </head> <body onload='document.loginForm.j_username.focus();'> <h3>Custom Login Page</h3> <% String errorString = (String)request.getAttribute("error"); if(errorString != null && errorString.trim().equals("true")){ out.println("<span class=\"dark\">Incorrect login name or password. Please try again"); } %> <form name='loginForm' action="<c:url value='login' />"" 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><input name="submit" type="submit" value="submit" /> </td> <td><input name="reset" type="reset" /> </td> </tr> </table> </form> </body> </html> |
We have used css file in above login.jsp. Create style.css file as below.
1 2 3 4 5 6 7 8 9 10 |
#header { font-size:40px; } .dark { color:red; } |
Step 6:
Create admin.jsp in /WEB-INF/pages folder.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Hello Admin</title> </head> <body> hello ${userName} !!! You are the admin <c:url value="/j_spring_security_logout" var="logoutUrl" /> <a href="${logoutUrl}">Log Out</a> </body> </html> |
Step 7:Create 403.jsp in /WEB-INF/pages folder.
1 2 3 4 5 6 7 8 9 10 11 |
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <body> <h1>HTTP Status 403 - Access is denied</h1> <h2>${msg}</h2> <c:url value="/j_spring_security_logout" var="logoutUrl" /> <a href="${logoutUrl}">Log Out</a> </body> </html> |
Step 8: Â
Now we need to add spring configuration xml. Create a file named spring-security.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<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-4.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd"> <http auto-config="true" use-expressions="true"> <intercept-url pattern="/resources/**" access="permitAll" /> <intercept-url pattern="/hello*" access="hasAnyRole('ROLE_ADMIN','ROLE_USER')" /> <intercept-url pattern="/admin**" access="hasRole('ROLE_ADMIN')" /> <form-login login-page="/login" default-target-url="/helloworld" authentication-failure-url="/loginError" /> <logout logout-success-url="/" logout-url="/j_spring_security_logout" /> <csrf disabled="true" /> <access-denied-handler error-page="/403" /> </http> <authentication-manager> <authentication-provider> <jdbc-user-service data-source-ref="dataSource" users-by-username-query="select username, password, active from users where username=?" authorities-by-username-query="select username, role from user_roles where username=?" /> </authentication-provider> </authentication-manager> </beans:beans> |
We have used form-login in above file, so if user tries to access any secured url, he will be authenticated based on above form-login configuration.
Lets understand meaning of each attribute of form-login tag
login-page : we need to provide url for login page.
default-target-url : here if authentication is successful, then target page url should be provided.
authentication-failure-url : if authentication is unsuccessful, then redirection page url should be provided here.
access-denied-handler : If user don’t have access to the page, /403 url will be called.
intercept-url configure for which pattern what kind of security is configured. For example: If http request url has pattern /hello*(hello.jsp,helloworld.html), it will be accessed to ROLE_ADMIN and ROLE_USER but if http request url has pattern /admin*,it will be accessed to ROLE_ADMIN only
We have provided queries for users-by-username-query and authorities-by-username-query to set up credentials for roles.
Step 9:Â
springmvc-dispatcher-servlet.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" 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/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <context:component-scan base-package="org.arpit.java2blog.springmvc.controller" /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix"> <value>/WEB-INF/pages/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> <mvc:annotation-driven/> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/CountryData" /> <property name="username" value="root" /> <property name="password" value="arpit123" /> </bean> <!-- Hibernate 4 SessionFactory Bean definition --> <bean id="hibernate4AnnotatedSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect </prop> <prop key="hibernate.show_sql">true</prop> </props> </property> </bean> </beans> |
Step 10:Â We need to change in web.xml to configure spring security.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <display-name>Archetype Created Web Application</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>springmvc-dispatcher</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc-dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/springmvc-dispatcher-servlet.xml, /WEB-INF/spring-security.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 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> |
It’s time for maven build.
Â
Run the application
  You will see below screen:
When you click on admin page link, you will get following login page. Now put User as arpit and password also as arpit.
We have put correct username and password , so we will see below screen.
If you use user john to access admin page, you will get below screens.
As john don’t have access to admin page, so you will get below screen.
Download source code:
Please comment if you have any issues with above post.
What you have posted is simply superb ,but i m looking for the example which involves the postgre sql database can you please post that .(at least how to change it from mysql to postgres).
_Thank u in advance
Hi Arpit . Thank you for the post its very helpful.
I request you share some examples on HTTP session in spring boot.please
Thank you in advance
Hi Arpit,
The content in the blog is very good to read and understand. Is there any possibility to view the content offline or any application associated to read it offline.
Regards
Santosh