場景
很多登錄都有記住我這個功能,在用戶登陸一次以后,系統會記住用戶一段時間,在這段時間,用戶不用反復登陸就可以使用我們的系統。記住用戶功能的基本原理如下圖:
用戶登錄的時候,請求發送給過濾器UsernamePasswordAuthenticationFilter,當該過濾器認證成功后,會調用RememberMeService,會生成一個token,將token寫入到瀏覽器cookie,同時RememberMeService里邊還有個TokenRepository,將token和用戶信息寫入到數據庫中。這樣當用戶再次訪問系統,訪問某一個接口時,會經過一個RememberMeAuthenticationFilter的過濾器,他會讀取cookie中的token,交給RememberService,RememberService會用TokenRepository根據token從數據庫中查是否有記錄,如果有記錄會把用戶名取出來,再調用UserDetailService根據用戶名獲取用戶信息,然后放在SecurityContext里。
實現類
首先來實現操作token的類,實現增刪改查功能,我們來使用redis保存,新建類RememberMeHandler,這個類需要實現接口 PersistentTokenRepository,首先來全局看一下類結構:
為了方便查詢,我們在記住一個用戶的時候,向redis中保存三條數據,其中兩個是根據series查用戶名和根據用戶名查series。token定義的保存時長為15天,這兩個定為30天。最下面的三個方法就是保存這兩個key的方法和生成所有key的方法。四個重寫的方法就是增刪改查方法。首先來看新增:
需要記住用戶的時候,把用戶的信息組合在一起,添加到redis中,並定義15天的過期時間。然后看修改和刪除:
都是對保存內容的正常操作,最后看查詢:
記住用戶之后,用戶登錄,查詢出用戶信息,實現自動認證。
網上有很多使用jdbc實現的方式,也是一種不錯的選擇。
配置記住我
在security配置類中,需要配置記住我的參數名字和處理類:
注意這里的授權配置要使用 authenticated() 。登錄頁面中增加記住我:
注意這里的參數名字 remember-me 是security記住我的默認名字。
測試
不勾選記住我,點擊登錄,redis中並沒有記錄token信息,勾選記住我,點擊登錄,可以看到記住我的信息記錄在redis中:
我們啟動項目,登錄成功並勾選記住用戶,然后重新啟動項目,在同一個瀏覽器中訪問頁面,可以看到不用登錄直接可以成功!