Spring Security form login using database

In this tutorial, we will show you how to perform database authentication (using both XML and Annotations) in Spring Security.


Technologies used :


Spring 3.2.8.RELEASE
Spring Security 3.2.3.RELEASE
Spring JDBC 3.2.3.RELEASE
Eclipse 4.2
JDK 1.6
Maven 3
Tomcat 6 or 7 (Servlet 3.x)
MySQL Server 5.6
Previous login-form in-memory authentication will be reused, enhance to support the following features :


Database authentication, using Spring-JDBC and MySQL.
Spring Security, JSP TagLib, sec:authorize access="hasRole('ROLE_USER')
Customize a 403 access denied page.
1. Project Demo
https://youtu.be/2ms57c2EdUg

2. Project Directory
Review the final project structure (XML-based) :
spring-security-database-xml-directory

spring-security-database-xml-directory
Review the final project structure (Annotation-based):
spring-security-database-annotation-directory

spring-security-database-annotation-directory
3. Project Dependencies
Get dependency for Spring, Spring Security, JDBC, Taglib and MySQL


pom.xml
<properties>
<jdk.version>1.6</jdk.version>
<spring.version>3.2.8.RELEASE</spring.version>
<spring.security.version>3.2.3.RELEASE</spring.security.version>
<jstl.version>1.2</jstl.version>
<mysql.connector.version>5.1.30</mysql.connector.version>
</properties>
 
<dependencies>
 
<!-- Spring 3 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</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
 
<!-- Spring Security -->
<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>
 
<!-- Spring Security JSP Taglib -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${spring.security.version}</version>
</dependency>
 
<!-- jstl for jsp page -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
 
                <!-- connect to mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>
 
</dependencies>
 
</project>
4. Database
To perform database authentication, you have to create tables to store the users and roles detail. Please refer to this Spring Security user-schema reference. Here are the MySQL scripts to create users and user_roles tables.


4.1 Create a “users” table.


users.sql
CREATE  TABLE users (
  username VARCHAR(45) NOT NULL ,
  password VARCHAR(45) NOT NULL ,
  enabled TINYINT NOT NULL DEFAULT 1 ,
  PRIMARY KEY (username));
4.2 Create a “user_roles” table.


user_roles.sql
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 uni_username_role (ROLE,username),
  KEY fk_username_idx (username),
  CONSTRAINT fk_username FOREIGN KEY (username) REFERENCES users (username));
4.3 Inserts some records for testing.


INSERT INTO users(username,password,enabled)
VALUES ('mkyong','123456', TRUE);
INSERT INTO users(username,password,enabled)
VALUES ('alex','123456', TRUE);
 
INSERT INTO user_roles (username, ROLE)
VALUES ('mkyong', 'ROLE_USER');
INSERT INTO user_roles (username, ROLE)
VALUES ('mkyong', 'ROLE_ADMIN');
INSERT INTO user_roles (username, ROLE)
VALUES ('alex', 'ROLE_USER');
Note
Username “mkyong”, with role_user and role_admin.
Username “alexa”, with role_user.
5. Spring Security Configuration
Spring Security in both XML and annotations.


5.1 Create a DataSource to connect MySQL.


spring-database.xml
<beans xmlns="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">
 
<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/test" />
<property name="username" value="root" />
<property name="password" value="password" />
</bean>
 
</beans>
The equivalent of the Spring annotations :


SecurityConfig.java
package com.mkyong.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.jdbc.datasource.DriverManagerDataSource;
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.mkyong.web.*" })
@Import({ SecurityConfig.class })
public class AppConfig {
 
@Bean(name = "dataSource")
public DriverManagerDataSource dataSource() {
   DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
   driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
   driverManagerDataSource.setUrl("jdbc:mysql://localhost:3306/test");
   driverManagerDataSource.setUsername("root");
   driverManagerDataSource.setPassword("password");
   return driverManagerDataSource;
}
 
@Bean
public InternalResourceViewResolver viewResolver() {
   InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
   viewResolver.setViewClass(JstlView.class);
   viewResolver.setPrefix("/WEB-INF/pages/");
   viewResolver.setSuffix(".jsp");
   return viewResolver;
}
 
}
5.2 Use jdbc-user-service to define a query to perform database authentication.


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">
 
    <!-- enable use-expressions -->
<http auto-config="true" use-expressions="true">
 
<intercept-url pattern="/admin**" access="hasRole('ROLE_ADMIN')" />
 
<!-- access denied page -->
<access-denied-handler error-page="/403" />
 
<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>
 
<!-- Select users and user_roles from database -->
<authentication-manager>
 <authentication-provider>
<jdbc-user-service data-source-ref="dataSource"
 users-by-username-query=
   "select username,password, enabled from users where username=?"
 authorities-by-username-query=
   "select username, role from user_roles where username =?  " />
 </authentication-provider>
</authentication-manager>
 
</beans:beans>
The equivalent of the Spring Security annotations :


SecurityConfig.java
package com.mkyong.config;
 
import javax.sql.DataSource;
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 SecurityConfig extends WebSecurityConfigurerAdapter {
 
@Autowired
DataSource dataSource;
 
@Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
 
 auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery(
"select username,password, enabled from users where username=?")
.authoritiesByUsernameQuery(
"select username, role from user_roles where username=?");
}
 
@Override
protected void configure(HttpSecurity http) throws Exception {
 
 http.authorizeRequests()
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
.and()
 .formLogin().loginPage("/login").failureUrl("/login?error")
 .usernameParameter("username").passwordParameter("password")
.and()
 .logout().logoutSuccessUrl("/login?logout")
.and()
 .exceptionHandling().accessDeniedPage("/403")
.and()
 .csrf();
}
}
6. JSP Pages
JSP pages for custom login page.


6.1 Default page, show the use of Spring Security JSP taglib sec:authorize to display content to users who have “ROLE_USER” authority.


hello.jsp
<%@taglib prefix="sec"
uri="http://www.springframework.org/security/tags"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
<h1>Title : ${title}</h1>
<h1>Message : ${message}</h1>
 
<sec:authorize access="hasRole('ROLE_USER')">
<!-- For login user -->
<c:url value="/j_spring_security_logout" var="logoutUrl" />
<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>
User : ${pageContext.request.userPrincipal.name} | <a
href="javascript:formSubmit()"> Logout</a>
</h2>
</c:if>
 
 
</sec:authorize>
</body>
</html>
6.2 Page to display the custom login form.


login.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@page session="true"%>
<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 οnlοad='document.loginForm.username.focus();'>
 
<h1>Spring Security Login Form (Database Authentication)</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'></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>
6.3 This page is password protected, only authenticated user “ROLE_ADMIN” is allowed to access.


admin.jsp
<%@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" />
<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>
6.4 Custom 403 access denied page.


403.jsp
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
<h1>HTTP Status 403 - Access is denied</h1>
 
<c:choose>
<c:when test="${empty username}">
 <h2>You do not have permission to access this page!</h2>
</c:when>
<c:otherwise>
 <h2>Username : ${username} <br/>
                    You do not have permission to access this page!</h2>
</c:otherwise>
</c:choose>
 
</body>
</html>
7. Spring MVC Controller
A simple controller.


MainController.java
package com.mkyong.web.controller;
 
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
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 MainController {
 
@RequestMapping(value = { "/", "/welcome**" }, method = RequestMethod.GET)
public ModelAndView defaultPage() {
 
 ModelAndView model = new ModelAndView();
 model.addObject("title", "Spring Security Login Form - Database Authentication");
 model.addObject("message", "This is default page!");
 model.setViewName("hello");
 return model;
 
}
 
@RequestMapping(value = "/admin**", method = RequestMethod.GET)
public ModelAndView adminPage() {
 
 ModelAndView model = new ModelAndView();
 model.addObject("title", "Spring Security Login Form - Database Authentication");
 model.addObject("message", "This page is for ROLE_ADMIN only!");
 model.setViewName("admin");
 return model;
 
}
 
@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;
 
}
 
//for 403 access denied page
@RequestMapping(value = "/403", method = RequestMethod.GET)
public ModelAndView accesssDenied() {
 
 ModelAndView model = new ModelAndView();
 
 //check if user is login
 Authentication auth = SecurityContextHolder.getContext().getAuthentication();
 if (!(auth instanceof AnonymousAuthenticationToken)) {
UserDetails userDetail = (UserDetails) auth.getPrincipal();
model.addObject("username", userDetail.getUsername());
 }
 
 model.setViewName("403");
 return model;
 
}
 
}
8. Demo
8.1. Default Page
XML – http://localhost:8080/spring-security-loginform-database/
Annotation – http://localhost:8080/spring-security-loginform-database-annotation/
spring-security-database-default

spring-security-database-default
8.2 Try to access /admin page, only “mkyong” ROLE_ADMIN is allowed to access.
spring-security-database-admin

spring-security-database-admin
8.3. If “alex” is try to access /admin, 403 access denied page is displayed.
spring-security-database-403

spring-security-database-403
8.3 “alex” in default page, show the use of sec:authorize
spring-security-database-sec-tag

spring-security-database-sec-tag
8.4. If “mkyong” is try to access /admin, admin page is displayed.

spring-security-database-admin-login

Download Source Code

http://www.mkyong.com/wp-content/uploads/2011/08/spring-security-login-form-database-xml.zip


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园的建设目标是通过数据整合、全面共享,实现校园内教学、科研、管理、服务流程的数字化、信息化、智能化和多媒体化,以提高资源利用率和管理效率,确保校园安全。 智慧校园的建设思路包括构建统一支撑平台、建立完善管理体系、大数据辅助决策和建设校园智慧环境。通过云架构的数据中心与智慧的学习、办公环境,实现日常教学活动、资源建设情况、学业水平情况的全面统计和分析,为决策提供辅助。此外,智慧校园还涵盖了多媒体教学、智慧录播、电子图书馆、VR教室等多种教学模式,以及校园网络、智慧班牌、校园广播等教务管理功能,旨在提升教学品质和管理水平。 智慧校园的详细方案设计进一步细化了教学、教务、安防和运维等多个方面的应用。例如,在智慧教学领域,通过多媒体教学、智慧录播、电子图书馆等技术,实现教学资源的共享和教学模式的创新。在智慧教务方面,校园网络、考场监控、智慧班牌等系统为校园管理提供了便捷和高效。智慧安防系统包括视频监控、一键报警、阳光厨房等,确保校园安全。智慧运维则通过综合管理平台、设备管理、能效管理和资产管理,实现校园设施的智能化管理。 智慧校园的优势和价值体现在个性化互动的智慧教学、协同高效的校园管理、无处不在的校园学习、全面感知的校园环境和轻松便捷的校园生活等方面。通过智慧校园的建设,可以促进教育资源的均衡化,提高教育质量和管理效率,同时保障校园安全和提升师生的学习体验。 总之,智慧校园解决方案通过整合现代信息技术,如云计算、大数据、物联网和人工智能,为教育行业带来了革命性的变革。它不仅提高了教育的质量和效率,还为师生创造了一个更加安全、便捷和富有智慧的学习与生活环境。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值