SpringSecurity RememberMe功能

一震蒋、前言

如SpringSecurity在用戶名密碼登錄的示例所示:
UsernamePasswordAuthenticationFilter的父類Filter中的 doFilter() 方法衷旅,調(diào)用用戶認(rèn)證的方法認(rèn)證用戶成功后供汛,會(huì)調(diào)用一個(gè)名為successfulAuthentication 的方法,它內(nèi)部有幾大過程洛波;

  • 1全肮、將認(rèn)證成功的信息存入SecurityContextHolder中塞蹭。
  • 2、如果rememberMeServices功能開啟了门坷,處理rememberMe的邏輯宣鄙。
  • 3、調(diào)用successHandler成功處理器默蚌。
    其中第二點(diǎn)就是今天要說的 "記住我" 的功能冻晤。它的實(shí)現(xiàn)邏輯如下:
rememberMe.png

二、流程梳理

1敏簿、第一次賦值流程(假設(shè)已經(jīng)開啟了rememberMe認(rèn)證流程)

PersistentTokenBasedRememberMeServices類中明也,先是生成一個(gè)PersistentRememberMeToken類型的 token宣虾,并通過tokenReposority.createNewToken(token)方法存儲(chǔ)這個(gè)token,最后將token信息存入cookie中返回前端温数。


這里的tokenReposority是需要我們自己配置的绣硝,SpringSecurity提前提供好了兩個(gè)可供使用的類

InMemoryTokenRepositoryImpl 
顧名思義,將token存儲(chǔ)在內(nèi)存中撑刺,特點(diǎn)是快鹉胖,但是消耗內(nèi)存,用戶量少的話可以使用够傍。內(nèi)部原理也很簡(jiǎn)單甫菠,就是將不同的token存儲(chǔ)在一個(gè)HashMap里面。

@Bean
public PersistentTokenRepository persistentTokenRepository(){
    InMemoryTokenRepositoryImpl tokenRepository = new InMemoryTokenRepositoryImpl ();
    return tokenRepository;
}

JdbcTokenRepositoryImpl
這個(gè)是將token存儲(chǔ)在數(shù)據(jù)庫中的選擇冕屯,下面setCreateTableOnStartup選中的ture會(huì)自動(dòng)在數(shù)據(jù)庫中創(chuàng)建一個(gè)表來存儲(chǔ)數(shù)據(jù)(第二次啟動(dòng)項(xiàng)目記得改為false寂诱,因?yàn)楸淼谝淮螁?dòng)已經(jīng)創(chuàng)建了,第二次還是true會(huì)報(bào)錯(cuò))

@Bean
public PersistentTokenRepository persistentTokenRepository(){
    JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
    tokenRepository.setCreateTableOnStartup(true);  
    tokenRepository.setDataSource(dataSource);
    return tokenRepository;
}

其實(shí)安聘,我們還可以自定義這個(gè)TokenRepository痰洒,只需要去實(shí)現(xiàn)上述說的兩個(gè)類的接口PersistentTokenRepository即可。

public interface PersistentTokenRepository {
    void createNewToken(PersistentRememberMeToken token);
    void updateToken(String series, String tokenValue, Date lastUsed);
    PersistentRememberMeToken getTokenForSeries(String seriesId);
    void removeUserTokens(String username);
}


2浴韭、過濾流程

第一次我登錄了之后丘喻,因?yàn)闀?huì)話的關(guān)系,我們可以訪問一些資源念颈。但是當(dāng)我關(guān)閉頁面泉粉,在會(huì)話消失后,我們的訪問一個(gè)后臺(tái)資源的話榴芳,按照以往的邏輯嗡靡,應(yīng)該是訪問不到且會(huì)跳轉(zhuǎn)到登錄頁面。但是如果我們之前的會(huì)話有RememberMe的話翠语,cookie中帶有一個(gè)名為remember-me的信息叽躯,在通過前面幾個(gè)過濾器之后,到了名為RememberMeAuthenticationFilter的過濾器中的時(shí)候肌括,它會(huì)從request中拿取cookie信息点骑,并嘗試通過token去獲取用戶信息,成功獲取到之后會(huì)通過UserDetailService認(rèn)證谍夭,認(rèn)證通過即可放行黑滴。

上面的aotuLogin()方法如下

最后,附上開啟記住我功能的配置

   // tokenRepository配置
    @Bean
    public PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setCreateTableOnStartup(false);
        tokenRepository.setDataSource(dataSource);
        return tokenRepository;
    }
    // 默認(rèn)的密碼加密
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    // 這個(gè)自定義即可
    @Bean
    public UserDetailsService demoUser() {
        return (username) -> new User(username, passwordEncoder().encode("123456"),
                AuthorityUtils.commaSeparatedStringToAuthorityList("admin,ROLE_USER"));
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
            http.formLogin()
                    .loginProcessingUrl("/testToLogin")
                    .loginPage("/needLogin")
                    .successHandler((request, response, authentication) -> {
                        PrintWriter writer = response.getWriter();
                        writer.print("強(qiáng)啊紧索,成了得嘛");
                    }).failureHandler((request, response, exception) -> {
                        response.setContentType("application/json;charset=UTF-8");
                        response.getWriter().write(om.writeValueAsString("login failure"));
                    })
                .and()
                    .rememberMe()            // -----------就是這里了
                    .alwaysRemember(true)      // 最近發(fā)現(xiàn)新版本要多配置一個(gè)這個(gè)袁辈,否則也沒有開啟
                    .tokenValiditySeconds(3600)
                    .tokenRepository(persistentTokenRepository())
                    .userDetailsService(demoUser())
                .and()
                .authorizeRequests()
                .antMatchers("/skip", "/needLogin").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .csrf().disable();
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市珠漂,隨后出現(xiàn)的幾起案子晚缩,更是在濱河造成了極大的恐慌尾膊,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件荞彼,死亡現(xiàn)場(chǎng)離奇詭異冈敛,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)鸣皂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門抓谴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人寞缝,你說我怎么就攤上這事癌压。” “怎么了荆陆?”我有些...
    開封第一講書人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵滩届,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我慎宾,道長(zhǎng)丐吓,這世上最難降的妖魔是什么浅悉? 我笑而不...
    開封第一講書人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任趟据,我火速辦了婚禮,結(jié)果婚禮上术健,老公的妹妹穿的比我還像新娘汹碱。我一直安慰自己,他們只是感情好荞估,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開白布咳促。 她就那樣靜靜地躺著,像睡著了一般勘伺。 火紅的嫁衣襯著肌膚如雪跪腹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,610評(píng)論 1 305
  • 那天飞醉,我揣著相機(jī)與錄音冲茸,去河邊找鬼。 笑死缅帘,一個(gè)胖子當(dāng)著我的面吹牛轴术,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播钦无,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼逗栽,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了失暂?” 一聲冷哼從身側(cè)響起彼宠,我...
    開封第一講書人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤鳄虱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后凭峡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體醇蝴,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年想罕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了悠栓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡按价,死狀恐怖惭适,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情楼镐,我是刑警寧澤癞志,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站框产,受9級(jí)特大地震影響凄杯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜秉宿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一戒突、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧描睦,春花似錦膊存、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至韵丑,卻和暖如春爵卒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背撵彻。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來泰國打工钓株, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人千康。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓享幽,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親拾弃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子值桩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355