Spring security實(shí)現(xiàn)記住我下次自動(dòng)登錄功能過(guò)程詳解
一、原理分析
第一次登陸時(shí),如果用戶勾選了readme選項(xiàng),登陸成功后springsecurity會(huì)生成一個(gè)cookie返回給瀏覽器端,瀏覽器下次訪問(wèn)時(shí)如果攜帶了這個(gè)cookie,springsecurity就會(huì)放行這次訪問(wèn)。
二、實(shí)現(xiàn)方式
2.1 簡(jiǎn)單實(shí)現(xiàn)方式
(1) 在springsecurity的配置文件中,http節(jié)點(diǎn)下增加一個(gè)remember-me配置
<security:http auto-config='true' use-expressions='false'> <!-- 配置鏈接地址,表示任意路徑都需要ROLE_USER權(quán)限,這里可以配置 一個(gè)逗號(hào)隔開(kāi)的角色列表--> <security:intercept-url pattern='/**' access='ROLE_USER'/> <!--自定義登錄頁(yè)面--> <security:form-login login-page='/login.html' login-processing-url='/login' username-parameter='username' password-parameter='password' authentication-failure-forward-url='/failed.html' default-target-url='/index.html' /> <!--關(guān)閉csrf,默認(rèn)是開(kāi)啟的--> <security:csrf disabled='true'/> <security:remember-me remember-me-parameter='remembermeParamater' /> <!-- 退出 --> <security:logout invalidate-session='true' logout-url='/logout.do' logout-success-url='/login.html'/> </security:http>
其中remember-me-parameter='remembermeParamater'指定前臺(tái)傳遞的是否rememberme的參數(shù)名,前臺(tái)要傳遞的參數(shù)值是true或false
(2)前臺(tái)登錄頁(yè)面上增加一個(gè)checkbox
<form action='/login' method='post'> 用戶名:<input type='text' name='username' placeholder='請(qǐng)輸入用戶名'><br> 密 碼:<input type='password' name='password' placeholder='請(qǐng)輸入密碼'><br> 記住我:<input type='checkbox' name='remembermeParamater' value='true'> <input type='submit' value='登錄'> </form>
checkbox的name屬性要和上邊配置文件中的remember-me-parameter='remembermeParamater'保持一致。
(3)測(cè)試
啟動(dòng)工程,進(jìn)行登錄,登錄成功后觀察cookie,會(huì)發(fā)現(xiàn)服務(wù)器端返回了一個(gè)名為remember-me的cookie
現(xiàn)在關(guān)閉瀏覽器,再次打開(kāi)并訪問(wèn),只要不清除cookie就可以直接訪問(wèn)資源,不需要重新登錄。
這種方式有個(gè)弊端,瀏覽器端要攜帶的這個(gè)cookie值服務(wù)端是存放在內(nèi)存中的,并沒(méi)有進(jìn)行持久化,所以如果服務(wù)重啟后服務(wù)器端存儲(chǔ)的這個(gè)值就會(huì)丟失,瀏覽器端的rememberme就會(huì)失效。為了解決這個(gè)問(wèn)題就需要將服務(wù)器端生成的這個(gè)cookie值持久化到數(shù)據(jù)庫(kù)中。
2.2 數(shù)據(jù)庫(kù)實(shí)現(xiàn)方式
(1)創(chuàng)建一張表用來(lái)持久化rememberme的記錄
-- 創(chuàng)建記錄rememberme記錄的表CREATE TABLE persistent_logins( username VARCHAR(64), series VARCHAR(64), token VARCHAR(64), last_used DATE );
(2)將spring-security 配置文件中的rememberme標(biāo)簽的內(nèi)容改為如下內(nèi)容
<security:remember-me remember-me-parameter='remembermeParamater' data-source-ref='dataSource' token-validity-seconds='86400'/>
data-source-ref='dataSource'用來(lái)指定數(shù)據(jù)源,spring-security通過(guò)數(shù)據(jù)源來(lái)操作數(shù)據(jù)庫(kù)中的persistent_logins表
token-validity-seconds表示rememberme的有效時(shí)間,以秒為單位,這里的86400=24*3600表示一天
(3)測(cè)試
啟動(dòng)工程,進(jìn)行登錄,登錄成功后會(huì)在persistent_logins表中生成一條記錄,
關(guān)閉瀏覽器再次訪問(wèn)時(shí)會(huì)根據(jù)瀏覽器中攜帶的cookie值來(lái)查找數(shù)據(jù)庫(kù)中的這條記錄,如果查詢到了就認(rèn)證通過(guò)
三、區(qū)分是密碼登錄還是rememberme登錄
在用戶進(jìn)行一些敏感操作時(shí),需要區(qū)分是否是rememberme登錄,如果是需要讓用戶跳轉(zhuǎn)到登錄頁(yè)面。
在congtroller層提供一個(gè)方法來(lái)進(jìn)行判斷
@GetMapping('/isRemembermeUser')public boolean isRemembermeUser(){ Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if(authentication==null){ return false; } //判斷當(dāng)前用戶是否是通過(guò)rememberme登錄,是返回true,否返回false return RememberMeAuthenticationToken.class.isAssignableFrom(authentication.getClass());}
先使用密碼登錄,訪問(wèn)http://localhost/user/isRemembermeUser.do,后臺(tái)接口返回false,再關(guān)閉瀏覽器再次訪問(wèn)這個(gè)地址,后臺(tái)接口返回true,表示這次是使用rememberme進(jìn)行的認(rèn)證。
測(cè)試工程代碼的地址:工程示例
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. Java8內(nèi)存模型PermGen Metaspace實(shí)例解析2. python excel和yaml文件的讀取封裝3. python如何實(shí)現(xiàn)word批量轉(zhuǎn)HTML4. python3實(shí)現(xiàn)往mysql中插入datetime類型的數(shù)據(jù)5. moment轉(zhuǎn)化時(shí)間戳出現(xiàn)Invalid Date的問(wèn)題及解決6. python爬蟲(chóng)實(shí)戰(zhàn)之制作屬于自己的一個(gè)IP代理模塊7. App啟動(dòng)優(yōu)化-Android性能優(yōu)化8. 詳解docker pull 下來(lái)的鏡像都存到了哪里9. Docker鏡像管理常用操作代碼示例10. python編寫(xiě)實(shí)現(xiàn)抽獎(jiǎng)器
