前一節學習了如何限制登錄嘗試次數,今天在這個基礎上再增加一點新功能: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
文章列表