本文是Spring Security系列中的一篇。在上一篇文章中,咱們經過實現UserDetailsService和UserDetails接口,實現了動態的從數據庫加載用戶、角色、權限相關信息,從而實現了登陸及受權相關的功能。這一節就在此基礎上新增,登陸過程當中常用的「記住我」功能,也就是咱們常常會在各類網站登錄時見到的"兩週內免登陸",「三天內免登陸」的功能。該功能的做用就是:當咱們登陸成功以後,必定的週期內當咱們再次訪問該網站,不須要從新登陸。spring
其實實現這個功能很是簡單,只須要咱們在重寫WebSecurityConfigurerAdapter 方法配置HttpSecurity 的時候增長rememberMe()方法。(下面代碼中省略了大量的關於Spring Security登陸驗證的配置,在本號此前的文章中已經講過)數據庫
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.rememberMe(); //實現記住我自動登陸配置,核心的代碼只有這一行 } }
而後在登陸表單中加入一個checkbox勾選框,name屬性的值目前必須是「remember-me」(個性化更改的方法後面會講)。瀏覽器
<label><input type="checkbox" name="remember-me">自動登陸</label>
就是這麼簡單,咱們就實現了記住我功能,默認效果是:2周內免登陸。安全
不少朋友可能看了上面的實現過程內心都犯懵,這樣就實現了?下面和你們說明一下這過程當中間,都作了哪些事情。springboot
這個token令牌是一個 MD5 hash字符串:包含username、expirationTime和passwod和一個預約義的key,並將他們通過MD5加密。可能有的朋友會問:這樣安全麼?若是cookie被劫持,必定是不安全的,別人拿到了這個字符串在有效期內就能夠訪問你的應用。這就和你的鑰匙token被盜了,你家確定不安全是一個道理。 可是不存在密碼被破解爲明文的可能性,MD5 hash是不可逆的。cookie
RememberMeAuthenticationFilter在Spring Security過濾器鏈中處於總體偏後的位置,因此只有當各類傳統的登陸方式都沒法完成驗證的狀況下,才走RememberMeAuthenticationFilter,這也是符合實際需求的。app
在實際的開發過程當中,咱們還能夠根據需求作一些個性化的設置,以下:ide
.rememberMe() .rememberMeParameter("remember-me-new") .rememberMeCookieName("remember-me-cookie") .tokenValiditySeconds(2 * 24 * 60 * 60);
上面咱們講的方式,就是最簡單的實現「記住我-自動登陸」功能的方式。這種方式的缺點在於:token與用戶的對應關係是在內存中存儲的,當咱們重啓應用以後全部的token都將消失,即:全部的用戶必須從新登錄。爲此,Spring Security還給咱們提供了一種將token存儲到數據庫中的方式,重啓應用也不受影響。學習
> 有的文章說使用數據庫存儲方式是由於這種方式更安全,筆者不這麼認爲。雖然數據庫存儲的token的確再也不是用戶名、密碼MD5加密字符串了,而是一個隨機序列號。可是一旦你的隨機序列號cookie被劫持,效果是同樣的。比如你家有把密碼鎖:你把鑰匙丟了和你把密碼丟了,危害性是同樣的。網站
上圖是token數據庫存儲方式的實現原理和驗證過程,下面咱們就來實現一下。首先,咱們須要鍵一張數據庫表persistent_logins:
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;
初始化一個PersistentTokenRepository類型的Spring bean,並將系統使用的DataSource注入到該bean中。(固然前提必定是你已經在Spring Boot的application.yml中配置好DataSource相關的鏈接屬性,這裏再也不贅述)
@Autowired private DataSource dataSource; @Bean public PersistentTokenRepository persistentTokenRepository(){ JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl(); tokenRepository.setDataSource(dataSource); return tokenRepository; }
最後在Spring Security配置方法configure(HttpSecurity http)加上以下的個性化配置:
.rememberMe() .tokenRepository(persistentTokenRepository())