漫步SpringSecurity---採用持久化token來實現remember-me功能(SpringBoot項目)

之前幾篇博客記錄了一下SpringSecurity一些基礎知識,也在整合Security那篇博客中記錄了remember-me的使用方法和一些基本原理。這一篇就來記錄一個和remember-me有關的一個操作,採用持久化token的方式來實現remember-me


本次記錄是在原有代碼上改動(實現好普通remember-me)功能的代碼

小前言

以前我們實現remember-me功能時,是直接在配置類相應方法中加入這一行代碼:

		http.rememberMe();

之後就會在登錄頁面自動生成這一個單選框。
在這裏插入圖片描述
當然如果我們需要自定義登錄頁的話,只需要在前端頁面添加一個radio的單選框,name爲remember-me,value爲true即可

問題剖析

上述的實現原理大致是用戶勾選該單選框之後,Security會爲我們在cookie中保存一個鍵值對,鍵爲remember-me,值爲系統生成的token。這個token是系統根據用戶名和密碼自動生成的,同時會設置上過期時間,只要我們在過期時間前訪問頁面,我們都會帶上這個cookie,而系統會根據token的值判斷該用戶是否已經登錄。

這是有一個問題,我們每次請求時,系統都會給我們帶回這個cookie信息,我們請求別的頁面時,會自動帶回給系統。但是如果有人惡意抓取了這個cookie信息,獲得了token那麼他就可以僞造用戶用戶去登錄了,這樣就有隱患。而且還有一種隱患token是根據用戶名和密碼加密生成的,萬一加密的渠道被破解了,那就等於變相把用戶名和密碼告訴別人了,所以我們需要採取另外一種方式來實現remember-me功能。

正文

這時我們採用持久化token的方式來存儲token

在客戶端的cookie中,僅保存一個無意義的加密串(與用戶名、密碼等敏感數據無關),然後在數據庫中保存該加密串-用戶信息的對應關係,自動登錄時,用cookie中的加密串,到db中驗證,如果通過,自動登錄纔算通過。

具體怎麼做呢?

首先需要在對應數據庫中創建一個表,這個表的表名和字段都是寫死的,不要改動。估計可能是底層sql語句就是固定寫好的。

CREATE TABLE persistent_logins (
  username varchar(64) not null,
  series varchar(64) not null,
  token varchar(64) not null,
  last_used timestamp not null,
  PRIMARY KEY (series)
);

創建好表之後,在配置類中注入一個數據庫連接池類:

    @Autowired
    private DataSource dataSource;

這裏因爲要持久化token,引入一個類jdbcTokenRepository,這個類實現了一個接口persistentTokenRepository,我們點進去這個接口:

public interface PersistentTokenRepository {
    void createNewToken(PersistentRememberMeToken var1);

    void updateToken(String var1, String var2, Date var3);

    PersistentRememberMeToken getTokenForSeries(String var1);

    void removeUserTokens(String var1);
}

看方法名字,不難發現這個接口實際上是對token進行增刪改查的。平時默認Security中會自動注入一個該接口的實現類InMemoryTokenRepositoryImpl,這個類存儲token是在內存中的。就是上文介紹的實現remember-me的方法,這個時候我們需要往ioc容器中注入另外一個接口實現類JdbcTokenRepositoryImpl,這個作用就是將token存儲在數據庫中。

在配置類中注入組件:

	//注入持久化token的組件
    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        return jdbcTokenRepository;

最後一步,指定使用的token存儲器(我這麼叫的.):

	http.rememberMe().tokenRepository(persistentTokenRepository()).tokenValiditySeconds(1209600);

第二個方法tokenRepository(persistentTokenRepository())就是指定token存儲器,tokenValiditySeconds(1209600)是設定過期時間。

我們登錄測試一下
在這裏插入圖片描述
去數據庫剛剛創建好的表中,可以看到裏面已經有數據了。

在這裏插入圖片描述
至此,我們的token就存儲在數據庫中,這樣安全性也得到了提高。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章