在之前的博客使用SpringMVC創建Web工程并使用SpringSecurity進行權限控制的詳細配置方法 中,我們描述了如何配置一個基于SpringMVC、SpringSecurity框架的網站系統。在這篇博客中,我們將繼續描述如何使用Spring Security進行登錄驗證。
總結一下Spring Security的登錄驗證關鍵步驟:
1、在數據庫中建好三張表,即users、authorities和persistent_logins三個。注意字段的定義,不能少,可以多,名字必須按規定來。
2、在Spring Security的配置文件中,配置好登錄跳轉的頁面,登錄處理的頁面和加密情況。
3、在前臺的jsp頁面中,登錄的字段必須和后臺users表中的一致,一般都是username和password。
4、注冊頁面必須自己寫,注冊的處理也要自己寫。
一、創建數據表
使用Spring Security進行登錄驗證,需要我們在數據庫中建好相應的表,并且字段要和Spring Security內置的字段一致。主要有3張表需要建立。一是users表,包含用戶名和密碼以及用戶狀態的表;第二個是authorities表,表明該用戶角色的,方便做角色控制,比如是ROLE_USER還是ROLE_ADMIN(比如admin頁面可能需要用戶的ROLE_ADMIN權限,而ROLE_USER權限無法登錄這個管理頁面);最后一個是persistent_logins表,是登錄狀態的記錄表,主要用來提供支持“記住我”功能的。三張表的創建語句如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
# 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的權限控制
配置Spring Security的控制信息就是配置哪些頁面需要登錄的用戶才能訪問,登錄的頁面是那一個,登陸成功跳轉到哪里等。以如下配置為例:所有的js等在resources文件夾下的內容都不需要經過過濾器,因為這些都是靜態資源。而首頁(/),登錄頁(/signin)、注冊頁(/register)等不需要用戶登錄,但是需要經過過濾器(因為我們可能需要獲取未登錄用戶的一些信息)。兩種配置方式如下所示。最后我們使用<form-login login-page="/signin" authentication-failure-url="/signin?login_error" default-target-url="/query"/>這個配置來說明登錄頁面是”/signin”,即所有需要用戶登錄的頁面,在用戶未登錄情況下需要跳轉到這個頁面,讓用戶登錄。authentication-failure-url配置的是用戶登錄失敗的頁面,而default-target-url是配置用戶登錄成功后跳轉的頁面。
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
|
<? 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的不經過任何spring的過濾器 --> < http pattern = "/resources/**" security = "none" /> < http pattern = "/sitemap.xml" security = "none" /> < http pattern = "/favicon.ico" security = "none" /> <!-- 配置為permitAll允許用戶訪問,但依然經過過濾器處理 --> < 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" />,表明登錄的時候會對密碼進行加密,那么后面我們寫注冊頁面的時候必須要對密碼加密之后才能存入數據庫。
三、創建登錄/注冊的頁面
這里屬于前臺的范疇,如果我們要使用Spring Security自帶的驗證方法,需要在前臺也配置一樣的信息來獲取驗證需要的字段,如用戶名和密碼。所以這里也是需要注意的地方。具體的頁面核心代碼如下(我們的頁面使用了Bootstrap的前端工具,所以要引入bootrap和jquery等外部樣式和腳本語言才會正常顯示,但是這些顯示不會影響功能,核心的字段不變即可):
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
|
< 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" >點擊登錄</ 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" >點擊注冊</ button > </ form > </ div > </ div > </ div > |
這里有兩個Tab頁代碼,一個是登錄Tab一個是注冊Tab。主要是登錄的Tab要和Spring Security一致,即登錄的處理應當是login,即action="login",用戶名的ID和name應該是username,而密碼的應該是password,即提交給登錄驗證的兩個參數應當是username和password,處理的請求頁是login。
四、創建注冊后臺,定義登錄處理
當登錄注冊頁面做好之后,需要定義一下處理請求,即跳轉的定義。然后只要寫注冊的后臺就行了。注意一點,Spring Security的注冊處理需要自己寫個后臺。用戶提交注冊后,我們需要把用戶名和密碼插入到數據庫中,又一點注意了,由于我們之前配置了密碼的加密,所以用戶注冊在插入數據庫之前需要加密,否則后面無法驗證通過。在注冊用戶的時候,我們需要更新users表的信息和authorities表信息,前者插入用戶名和密碼,并使得enabled=1(這個字段表示用戶是否正常,=0的話,狀態就是鎖定的)。在authorities中要寫入用戶對應的角色(權限)。用戶注冊的時候密碼加密的關鍵代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
//插入users表的語句 String addUser = "insert into users(username,password) values(?,?)" ; //對密碼參數進行加密 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(); } |
加密的代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/** * BCrypt加密(適用于注冊時密碼加密) * * @param rawPassword 明文密碼 * @return encoderPassword 密文密碼,長度為60 */ public static String encode(String rawPassword) { // 調用spring security的BCrypt加密 BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); String encoderPassword = encoder.encode(rawPassword); return encoderPassword; } |
這樣,用戶就可以注冊了。注冊好了就可以使用登錄功能了。
總結一下Spring Security的登錄驗證關鍵步驟:
1、在數據庫中建好三張表,即users、authorities和persistent_logins三個。注意字段的定義,不能少,可以多,名字必須按規定來。
2、在Spring Security的配置文件中,配置好登錄跳轉的頁面,登錄處理的頁面和加密情況。
3、在前臺的jsp頁面中,登錄的字段必須和后臺users表中的一致,一般都是username和password。
4、注冊頁面必須自己寫,注冊的處理也要自己寫。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://blog.csdn.net/df19900725/article/details/78085152?utm_source=tuicool&utm_medium=referral