詳解使用Spring Security進(jìn)行自動登錄驗(yàn)證
在之前的博客使用SpringMVC創(chuàng)建Web工程并使用SpringSecurity進(jìn)行權(quán)限控制的詳細(xì)配置方法 中,我們描述了如何配置一個基于SpringMVC、SpringSecurity框架的網(wǎng)站系統(tǒng)。在這篇博客中,我們將繼續(xù)描述如何使用Spring Security進(jìn)行登錄驗(yàn)證。
總結(jié)一下Spring Security的登錄驗(yàn)證關(guān)鍵步驟:
1、在數(shù)據(jù)庫中建好三張表,即users、authorities和persistent_logins三個。注意字段的定義,不能少,可以多,名字必須按規(guī)定來。
2、在Spring Security的配置文件中,配置好登錄跳轉(zhuǎn)的頁面,登錄處理的頁面和加密情況。
3、在前臺的jsp頁面中,登錄的字段必須和后臺users表中的一致,一般都是username和password。
4、注冊頁面必須自己寫,注冊的處理也要自己寫。
一、創(chuàng)建數(shù)據(jù)表
使用Spring Security進(jìn)行登錄驗(yàn)證,需要我們在數(shù)據(jù)庫中建好相應(yīng)的表,并且字段要和Spring Security內(nèi)置的字段一致。主要有3張表需要建立。一是users表,包含用戶名和密碼以及用戶狀態(tài)的表;第二個是authorities表,表明該用戶角色的,方便做角色控制,比如是ROLE_USER還是ROLE_ADMIN(比如admin頁面可能需要用戶的ROLE_ADMIN權(quán)限,而ROLE_USER權(quán)限無法登錄這個管理頁面);最后一個是persistent_logins表,是登錄狀態(tài)的記錄表,主要用來提供支持“記住我”功能的。三張表的創(chuàng)建語句如下:
#create users table CREATE TABLE `users` ( `username` varchar(100) NOT NULL, `password` varchar(100) NOT NULL, `enabled` tinyint(1) NOT NULL DEFAULT '1', UNIQUE KEY `account` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; #create authorities table CREATE TABLE `authorities` ( `username` varchar(50) NOT NULL, `authority` varchar(50) DEFAULT NULL, PRIMARY KEY (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; #create persistent_logins table CREATE TABLE `persistent_logins` ( `username` varchar(64) NOT NULL, `series` varchar(64) NOT NULL, `token` varchar(64) NOT NULL, `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`series`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
記住,這三張表字段一定要至少包含以上字段。這樣Spring Security才能識別。但是,我們也可以額外添加一些字段,比如在users中添加uid等。
二、配置Spring Security的權(quán)限控制
配置Spring Security的控制信息就是配置哪些頁面需要登錄的用戶才能訪問,登錄的頁面是那一個,登陸成功跳轉(zhuǎn)到哪里等。以如下配置為例:所有的js等在resources文件夾下的內(nèi)容都不需要經(jīng)過過濾器,因?yàn)檫@些都是靜態(tài)資源。而首頁(/),登錄頁(/signin)、注冊頁(/register)等不需要用戶登錄,但是需要經(jīng)過過濾器(因?yàn)槲覀兛赡苄枰@取未登錄用戶的一些信息)。兩種配置方式如下所示。最后我們使用<form-login login-page="/signin" authentication-failure-url="/signin?login_error" default-target-url="/query"/>這個配置來說明登錄頁面是”/signin”,即所有需要用戶登錄的頁面,在用戶未登錄情況下需要跳轉(zhuǎn)到這個頁面,讓用戶登錄。authentication-failure-url配置的是用戶登錄失敗的頁面,而default-target-url是配置用戶登錄成功后跳轉(zhuǎn)的頁面。
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
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">
<!-- 配置為none的不經(jīng)過任何spring的過濾器 -->
<http pattern="/resources/**" security="none" />
<http pattern="/sitemap.xml" security="none" />
<http pattern="/favicon.ico" security="none" />
<!-- 配置為permitAll允許用戶訪問,但依然經(jīng)過過濾器處理 -->
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/" access="permitAll" />
<intercept-url pattern="/index*" access="permitAll" />
<intercept-url pattern="/signin*" access="permitAll" />
<intercept-url pattern="/login*" access="permitAll" />
<intercept-url pattern="/register*" access="permitAll" />
<intercept-url pattern="/invalidsession*" access="permitAll" />
<intercept-url pattern="/404*" access="none" />
<form-login login-page="/signin" authentication-failure-url="/signin?login_error" default-target-url="/query"/>
<logout logout-success-url="/query" delete-cookies="JSESSIONID" />
<intercept-url pattern="/admin" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/**" access="hasAnyRole('ROLE_ADMIN','ROLE_USER')" />
<csrf disabled="true" />
<access-denied-handler error-page="/403" />
<remember-me data-source-ref="dataSource" token-validity-seconds="1209600" remember-me-parameter="remember-me" />
<session-management invalid-session-url="/">
<concurrency-control max-sessions="1"/>
</session-management>
</http>
<authentication-manager erase-credentials="false">
<authentication-provider>
<password-encoder ref="bcryptEncoder" />
<jdbc-user-service data-source-ref="dataSource" />
</authentication-provider>
</authentication-manager>
<beans:bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<beans:property name="basenames">
<beans:list>
<beans:value>classpath:myMessages</beans:value>
</beans:list>
</beans:property>
</beans:bean>
<beans:bean name="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
</beans:beans>
注意,這里定義了<beans:bean name="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />,表明登錄的時候會對密碼進(jìn)行加密,那么后面我們寫注冊頁面的時候必須要對密碼加密之后才能存入數(shù)據(jù)庫。
三、創(chuàng)建登錄/注冊的頁面
這里屬于前臺的范疇,如果我們要使用Spring Security自帶的驗(yàn)證方法,需要在前臺也配置一樣的信息來獲取驗(yàn)證需要的字段,如用戶名和密碼。所以這里也是需要注意的地方。具體的頁面核心代碼如下(我們的頁面使用了Bootstrap的前端工具,所以要引入bootrap和jquery等外部樣式和腳本語言才會正常顯示,但是這些顯示不會影響功能,核心的字段不變即可):
<div class="container">
<!-- 頁面切換代碼 -->
<ul class="nav nav-tabs" id="loginTab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="home-tab" data-toggle="tab" href="#login" rel="external nofollow"
role="tab" aria-controls="home" aria-expanded="true">登錄</a>
</li>
<li class="nav-item">
<a class="nav-link" id="home-tab" data-toggle="tab" href="#register" rel="external nofollow"
role="tab" aria-controls="home" aria-expanded="true">注冊</a>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<!-- 登錄頁面 -->
<div id="login" class="tab-pane fade show active" role="tabpanel" aria-labelledby="login-tab">
<form class="form-signin" action="login" method="post">
<label for="username" class="sr-only">Email address</label>
<input type="email" name="username" id="username" class="form-control" placeholder="郵件地址">
<label for="password" class="sr-only">Password</label>
<input type="password" name="password" id="password" class="form-control" placeholder="密碼">
<button class="btn btn-lg btn-primary btn-block" type="submit">點(diǎn)擊登錄</button>
</form>
</div>
<!-- 注冊頁面 -->
<div id="register" class="tab-pane fade" role="tabpanel" aria-labelledby="register-tab">
<div id="register_attention_alert_reg"></div>
<form class="form-signin" onsubmit="return register()" method="post">
<label for="registerEmail" class="sr-only">Email address</label>
<input type="email" id="registerEmail" name="registerEmail" class="form-control" placeholder="郵件地址">
<label for="registerPassword" class="sr-only">Password</label>
<input type="password" name="password" id="registerPassword" class="form-control" placeholder="密碼">
<label for="inputPassword2" class="sr-only">Password</label>
<input type="password" id="inputPasswordForRegister2" class="form-control" placeholder="請再次輸入密碼">
<button class="btn btn-lg btn-primary btn-block" onclick="submit">點(diǎn)擊注冊</button>
</form>
</div>
</div>
</div>

這里有兩個Tab頁代碼,一個是登錄Tab一個是注冊Tab。主要是登錄的Tab要和Spring Security一致,即登錄的處理應(yīng)當(dāng)是login,即action="login",用戶名的ID和name應(yīng)該是username,而密碼的應(yīng)該是password,即提交給登錄驗(yàn)證的兩個參數(shù)應(yīng)當(dāng)是username和password,處理的請求頁是login。
四、創(chuàng)建注冊后臺,定義登錄處理
當(dāng)?shù)卿涀皂撁孀龊弥?,需要定義一下處理請求,即跳轉(zhuǎn)的定義。然后只要寫注冊的后臺就行了。注意一點(diǎn),Spring Security的注冊處理需要自己寫個后臺。用戶提交注冊后,我們需要把用戶名和密碼插入到數(shù)據(jù)庫中,又一點(diǎn)注意了,由于我們之前配置了密碼的加密,所以用戶注冊在插入數(shù)據(jù)庫之前需要加密,否則后面無法驗(yàn)證通過。在注冊用戶的時候,我們需要更新users表的信息和authorities表信息,前者插入用戶名和密碼,并使得enabled=1(這個字段表示用戶是否正常,=0的話,狀態(tài)就是鎖定的)。在authorities中要寫入用戶對應(yīng)的角色(權(quán)限)。用戶注冊的時候密碼加密的關(guān)鍵代碼如下:
//插入users表的語句
String addUser = "insert into users(username,password) values(?,?)";
//對密碼參數(shù)進(jìn)行加密
String pwd = SpringSecurityUtil.encode(password);
Object[] param = {email, pwd};
//插入authorities表的語句
String addAuthority = "insert into authorities(username,authority) values(?,'ROLE_USER')";
Object[] authorityParam = {email};
int rows = 0;
try {
rows = MyQueryRunnerUtil.getQueryRunner().update(addUser, param);
rows += MyQueryRunnerUtil.getQueryRunner().update(addAuthority, authorityParam);
} catch (SQLException e) {
e.printStackTrace();
}
加密的代碼如下:
/**
* BCrypt加密(適用于注冊時密碼加密)
*
* @param rawPassword 明文密碼
* @return encoderPassword 密文密碼,長度為60
*/
public static String encode(String rawPassword) {
// 調(diào)用spring security的BCrypt加密
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String encoderPassword = encoder.encode(rawPassword);
return encoderPassword;
}
這樣,用戶就可以注冊了。注冊好了就可以使用登錄功能了。
總結(jié)一下Spring Security的登錄驗(yàn)證關(guān)鍵步驟:
1、在數(shù)據(jù)庫中建好三張表,即users、authorities和persistent_logins三個。注意字段的定義,不能少,可以多,名字必須按規(guī)定來。
2、在Spring Security的配置文件中,配置好登錄跳轉(zhuǎn)的頁面,登錄處理的頁面和加密情況。
3、在前臺的jsp頁面中,登錄的字段必須和后臺users表中的一致,一般都是username和password。
4、注冊頁面必須自己寫,注冊的處理也要自己寫。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 詳解使用Spring Security OAuth 實(shí)現(xiàn)OAuth 2.0 授權(quán)
- 基于Spring Security的Oauth2授權(quán)實(shí)現(xiàn)方法
- Spring Security OAuth2認(rèn)證授權(quán)示例詳解
- Spring Security 控制授權(quán)的方法
- Spring Security OAuth 自定義授權(quán)方式實(shí)現(xiàn)手機(jī)驗(yàn)證碼
- Spring?Security使用數(shù)據(jù)庫登錄認(rèn)證授權(quán)
- Spring Security實(shí)現(xiàn)微信公眾號網(wǎng)頁授權(quán)功能
- SpringBoot Security前后端分離登錄驗(yàn)證的實(shí)現(xiàn)
- 解析SpringSecurity自定義登錄驗(yàn)證成功與失敗的結(jié)果處理問題
- 詳解Spring Security中的HttpBasic登錄驗(yàn)證模式
- 淺析Spring Security登錄驗(yàn)證流程源碼
- SpringSecurity頁面授權(quán)與登錄驗(yàn)證實(shí)現(xiàn)(內(nèi)存取值與數(shù)據(jù)庫取值)
相關(guān)文章
springboot集成kafka消費(fèi)手動啟動停止操作
這篇文章主要介紹了springboot集成kafka消費(fèi)手動啟動停止操作,本文給大家介紹項目場景及解決分析,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09
Java讀取properties文件連接數(shù)據(jù)庫的方法示例
這篇文章主要介紹了Java讀取properties文件連接數(shù)據(jù)庫的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-04-04
帶你了解Java數(shù)據(jù)結(jié)構(gòu)和算法之2-3-4樹
這篇文章主要為大家介紹了Java數(shù)據(jù)結(jié)構(gòu)和算法之2-3-4樹,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-01-01

