文章出處

前一節學習了如何限制登錄嘗試次數,今天在這個基礎上再增加一點新功能:Remember Me. 很多網站,比如博客園,在登錄頁面就有這個選項,勾選“下次自動登錄”后,在一定時間段內,只要不清空瀏覽器Cookie,就可以自動登錄。

一、spring-security.xml 最簡單的配置

1     <http auto-config="true" use-expressions="true">
2         ...
3         <remember-me />
4     </http>

即:在<http></http>節點之間,加一行<rember-me/>,然后

1  <authentication-manager erase-credentials="false">  
2       ...
3 </authentication-manager> 

 在<authentication-manager>節點增加一個屬性erase-credentials="false" ,配置的修改就算完了

二、登錄頁login.jsp

1 <input id="_spring_security_remember_me" name="_spring_security_remember_me" type="checkbox" value="true"/>

 加上這個checkbox勾選框即可

原理簡析:按上面的步驟修改后,如果在登錄時勾選了Remember Me,登錄成功后,會在瀏覽器中生成一個名為SPRING_SECURITY_REMEMBER_ME_COOKIE的Cookie項,默認有效值為2周,其值是一個加密字符串,其值據說與用戶名、密碼等敏感數據有關!

下次再進入該頁面時,Spring Security的springSecurityFilterChain這個Filter會檢測有沒有這個Cookie,如果有,就自動登錄。

三、安全性分析

安全性分析:這樣雖然很方便,但是大家都知道Cookie畢竟是保存在客戶端的,很容易盜取,而且cookie的值還與用戶名、密碼這些敏感數據相關,雖然加密了,但是將敏感信息存在客戶端,畢竟不太安全。

建議:對于一些重要操作,比如:電子商務中的在線支付、修改用戶密碼等需要本人親自操作的業務環節,還是要將用戶引導至登錄頁,重新登錄,以保證安全。為了達到這個目的,代碼就必須在jsp前端以java后端,有辦法檢測出當前登錄的用戶,是否通過“Remember Me Cookie”自動登錄,還是通過“輸入用戶名、密碼”安全登錄。

在jsp前端檢查是否Remember Me自動登錄很簡單,直接使用security提供的tag標簽即可,類似下面這樣:

1 <%@taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
2 ...
3 <sec:authorize access="isRememberMe()">
4         ...    
5 </sec:authorize>

在java 服務端的Controller中,可這樣檢測:

 1     /**
 2      * 判斷用戶是否從Remember Me Cookie自動登錄
 3      * @return
 4      */
 5     private boolean isRememberMeAuthenticated() {
 6 
 7         Authentication authentication = SecurityContextHolder.getContext()
 8                 .getAuthentication();
 9         if (authentication == null) {
10             return false;
11         }
12 
13         return RememberMeAuthenticationToken.class
14                 .isAssignableFrom(authentication.getClass());
15     }

此外,spring security還提供了remember me的另一種相對更安全的實現機制 :在客戶端的cookie中,僅保存一個無意義的加密串(與用戶名、密碼等敏感數據無關),然后在db中保存該加密串-用戶信息的對應關系,自動登錄時,用cookie中的加密串,到db中驗證,如果通過,自動登錄才算通過。

先在db中創建一張表:

 1 --Remember Me持久化保存記錄
 2 create table PERSISTENT_LOGINS
 3 (
 4   username  VARCHAR2(64) not null,
 5   series   VARCHAR2(64) not null,
 6   token     VARCHAR2(64) not null,
 7   last_used DATE not null
 8 );
 9 
10 alter table PERSISTENT_LOGINS
11   add constraint PK_PERSISTENT_LOGIN primary key (series);

然后將spring-security.xml中<remember-me/> 改為:

1 <remember-me data-source-ref="dataSource" 
2         token-validity-seconds="1209600" 
3         remember-me-parameter="remember-me" />

data-source-ref指定數據源,token-validity-seconds表示cookie的有效期(秒為單位),remember-me-parameter對應登錄頁上checkbox的名字。

這樣處理后,勾選Remember me登錄會在PERSISTENT_LOGINS表中,生成一條記錄:

logout時,該記錄以及客戶端的cookie都會同時清空。

最后,如果不想用默認的表名persistent_logins,可研究下:

org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl

org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices

這二個類的源碼 以及 相關文章:

http://forum.spring.io/forum/spring-projects/security/126343-spring-3-1-persistenttokenbasedremembermeservices-and-usernamepasswordauthentication

http://www.fengfly.com/document/springsecurity3/remember-me.html

http://docs.huihoo.com/spring/spring-security/3.0.x/remember-me.html#remember-me-persistent-token

示例源碼:SpringSecurity-Remember-Me-XML(0722).zip

參考文章:Spring Security Remember Me Example


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()