Spring Security笔记:使用数据库进行用户认证(form login using database) - 菩提树下的杨过 - 博客园
在前一节,学习了如何自定义登录页,但是用户名、密码仍然是配置在xml中的,这样显然太非主流,本节将学习如何把用户名/密码/角色存储在db中,通过db来实现用户认证
一、项目结构
与前面的示例相比,因为要连接db,所以多出了一个spring-database.xml用来定义数据库连接,此外,为了演示登录用户权限不足的场景,加了一个页面403.jsp,用来统一显示权限不足的提示信息
二、数据库表结构(oracle环境)
![](http://images0.cnblogs.com/blog/479631/201411/031707119552013.gif)
1 create table T_USERS 2 ( 3 d_username VARCHAR2(50) not null, 4 d_password VARCHAR2(60), 5 d_enabled NUMBER(1) 6 ); 7 alter table T_USERS 8 add constraint PK_USERS_USERNAME primary key (D_USERNAME) ; 9 10 create table T_USER_ROLES 11 ( 12 d_user_role_id NUMBER(10) not null, 13 d_username VARCHAR2(50), 14 d_role VARCHAR2(50) 15 ); 16 alter table T_USER_ROLES 17 add constraint PK_USER_ROLES primary key (D_USER_ROLE_ID); 18 alter table T_USER_ROLES 19 add constraint IDX_UNI_ROLE_USERNAME unique (D_USERNAME, D_ROLE);
这里创建了二张表,一张用来保存用户名/密码,另一张用来保存用户所属的权限角色,表名和字段名无所谓,可以随便改,但是用户表中,必须要有"用户名/密码/帐号的有效状态"这三列信息,权限角色表必须要有“用户名/权限角色”这二列信息
再insert几条测试数据
![](http://images0.cnblogs.com/blog/479631/201411/031707116114584.gif)
这里插入了二个用户YJMYZZ/MIKE,而且MIKE属于POWER组,YJMYZZ同时属于POWER\ADMIN二个权限组
三、spring-security.xml
![](http://images0.cnblogs.com/blog/479631/201411/031707119552013.gif)
1 <beans:beans xmlns="http://www.springframework.org/schema/security" 2 xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://www.springframework.org/schema/beans 4 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 5 http://www.springframework.org/schema/security 6 http://www.springframework.org/schema/security/spring-security-3.2.xsd"> 7 8 <http auto-config="true" use-expressions="true"> 9 <intercept-url pattern="/admin**" access="hasRole('ADMIN')" /> 10 <!-- access denied page --> 11 <access-denied-handler error-page="/403" /> 12 <form-login login-page="/login" default-target-url="/welcome" 13 authentication-failure-url="/login?error" username-parameter="username" 14 password-parameter="password" /> 15 <logout logout-success-url="/login?logout" /> 16 <!-- enable csrf protection --> 17 <csrf /> 18 </http> 19 20 <!-- Select users and user_roles from database --> 21 <authentication-manager> 22 <authentication-provider> 23 <jdbc-user-service data-source-ref="dataSource" 24 users-by-username-query="select d_username username,d_password password, d_enabled enabled from t_users where d_username=?" 25 authorities-by-username-query="select d_username username, d_role role from t_user_roles where d_username=? " /> 26 </authentication-provider> 27 </authentication-manager> 28 29 </beans:beans>
注意第9行,这里使用了一个el表达式,目的是/admin开头的url,必须有ADMIN角色的登录用户才可访问
第11行,表示如果登录用户权限不够,将跳转到/403这个url
24,25这二行,指定了查询用户/角色的sql语句,注意:虽然前面提到了用户/角色这二张表的表名/字段名可以随便写,但是写sql时,用户名的别名必须是username,密码列的别名必须是password,帐号有效状态的别名必须是enabled,而权限角色列的别名必须是role
23行指定了db数据源,它的详细定义在 spring-database.xml中,内容如下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans.xsd"> 6 7 <bean id="dataSource" 8 class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 9 <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> 10 <property name="url" value="jdbc:oracle:thin:@172.21.***.***:1521:orcl" /> 11 <property name="username" value="***" /> 12 <property name="password" value="***" /> 13 </bean> 14 </beans>
本文使用的是oracle数据库,如果是其它数据库,请自行调整上面的内容
四、Controller
![](http://images0.cnblogs.com/blog/479631/201411/031707116114584.gif)
66-71行演示了如何在服务端判断一个用户是否已经登录
五、视图页面
hello.jsp
![](http://images0.cnblogs.com/blog/479631/201411/031707116114584.gif)
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <%@taglib prefix="sec" 4 uri="http://www.springframework.org/security/tags"%> 5 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 6 <html> 7 <head> 8 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 9 <title>${title}</title> 10 </head> 11 <body> 12 <h1>Title : ${title}</h1> 13 <h1>Message : ${message}</h1> 14 <sec:authorize access="hasRole('POWER')"> 15 <!-- For login user --> 16 <c:url value="/j_spring_security_logout" var="logoutUrl" /> 17 <form action="${logoutUrl}" method="post" id="logoutForm"> 18 <input type="hidden" name="${_csrf.parameterName}" 19 value="${_csrf.token}" /> 20 </form> 21 <script> 22 function formSubmit() { 23 document.getElementById("logoutForm").submit(); 24 } 25 </script> 26 27 <c:if test="${pageContext.request.userPrincipal.name != null}"> 28 <h2> 29 User : ${pageContext.request.userPrincipal.name} | <a 30 href="javascript:formSubmit()"> Logout</a> | <a href="admin">admin</a> 31 </h2> 32 </c:if> 33 </sec:authorize> 34 35 <sec:authorize access="isAnonymous()"> 36 <br /> 37 <h2> 38 <a href="login">login</a> 39 </h2> 40 </sec:authorize> 41 42 </body> 43 </html>
注意一下:14、27、35这三行,它们演示了如何在jsp端判断用户具有的角色权限、是否已登录等用法
403.jsp
![](http://images0.cnblogs.com/blog/479631/201411/031707116114584.gif)
1 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 2 <html> 3 <body> 4 <h1>HTTP Status 403 - Access is denied</h1> 5 6 <c:choose> 7 <c:when test="${empty username}"> 8 <h2>You do not have permission to access this page!</h2> 9 </c:when> 10 <c:otherwise> 11 <h2> 12 Username : ${username} <br /> You do not have permission to access 13 this page! 14 </h2> 15 </c:otherwise> 16 </c:choose> 17 18 </body> 19 </html>
admin.jsp
![](http://images0.cnblogs.com/blog/479631/201411/031707116114584.gif)
1 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 2 <%@page session="true"%> 3 <html> 4 <body> 5 <h1>Title : ${title}</h1> 6 <h1>Message : ${message}</h1> 7 8 <c:url value="/j_spring_security_logout" var="logoutUrl" /> 9 <form action="${logoutUrl}" method="post" id="logoutForm"> 10 <input type="hidden" name="${_csrf.parameterName}" 11 value="${_csrf.token}" /> 12 </form> 13 <script> 14 function formSubmit() { 15 document.getElementById("logoutForm").submit(); 16 } 17 </script> 18 19 <c:if test="${pageContext.request.userPrincipal.name != null}"> 20 <h2> 21 Welcome : ${pageContext.request.userPrincipal.name} | <a 22 href="javascript:formSubmit()"> Logout</a> | <a href="welcome">welcome</a> 23 </h2> 24 </c:if> 25 26 </body> 27 </html>
因为在xml中已经配置了/admin开头的请求url,必须具有ADMIN角色权限,所以admin.jsp端反而不用任何额外的判断了
文中示例源代码下载:SpringSecurity-LoginForm-Database-XML.zip
参考文章: Spring Security Form Login Using Database
作者:少帅
出处:少帅的博客--http://www.cnblogs.com/wang3680
您的支持是对博主最大的鼓励,感谢您的认真阅读。
本文版权归作者所有,欢迎转载,但请保留该声明。
![](https://images.cnblogs.com/cnblogs_com/wang3680/1880988/o_201113031241%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20201113111211.jpg)
![](https://images.cnblogs.com/cnblogs_com/wang3680/1881010/o_201113034037%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20201113113928.png)