1. 程式人生 > >SpringBoot集成Spring Security(2)——自動登錄

SpringBoot集成Spring Security(2)——自動登錄

ofo 關閉 eat con bean ber div 語句 button

在上一章:SpringBoot集成Spring Security(1)——入門程序中,我們實現了入門程序,本篇為該程序加上自動登錄的功能。

文章目錄

一、修改login.html
二、兩種實現方式
  2.1 Cookie 存儲
  2.2 數據庫存儲
  2.2.1 基本原理
  2.2.2 代碼實現
三、運行程序


源碼地址:https://github.com/jitwxs/blog_sample


一、修改login.html

在登陸頁添加自動登錄的選項,註意自動登錄字段的 name 必須是 remember-me

<!DOCTYPE html>
<html lang="en">
<head> <meta charset="UTF-8"> <title>登陸</title> </head> <body> <h1>登陸</h1> <form method="post" action="/login"> <div> 用戶名:<input type="text" name="username"> </div> <div> 密碼:<input type="password"
name="password"> </div> <div> <label><input type="checkbox" name="remember-me"/>自動登錄</label> <button type="submit">立即登陸</button> </div> </form> </body> </html>

二、兩種實現方式

2.1 Cookie 存儲

這種方式十分簡單,只要在 WebSecurityConfig 中的 configure() 方法添加一個 rememberMe()

即可,如下所示:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            // 如果有允許匿名的url,填在下面
//                .antMatchers().permitAll()
            .anyRequest().authenticated()
            .and()
            // 設置登陸頁
            .formLogin().loginPage("/login")
            // 設置登陸成功頁
            .defaultSuccessUrl("/").permitAll()
            // 自定義登陸用戶名和密碼參數,默認為username和password
//                .usernameParameter("username")
//                .passwordParameter("password")
            .and()
            .logout().permitAll()
            // 自動登錄
            .and().rememberMe();

    // 關閉CSRF跨域
    http.csrf().disable();
}

當我們登陸時勾選自動登錄時,會自動在 Cookie 中保存一個名為 remember-me 的cookie,默認有效期為2周,其值是一個加密字符串:

技術分享圖片

2.2 數據庫存儲

使用 Cookie 存儲雖然很方便,但是大家都知道 Cookie 畢竟是保存在客戶端的,而且 Cookie 的值還與用戶名、密碼這些敏感數據相關,雖然加密了,但是將敏感信息存在客戶端,畢竟不太安全。

Spring security 還提供了另一種相對更安全的實現機制:在客戶端的 Cookie 中,僅保存一個無意義的加密串(與用戶名、密碼等敏感數據無關),然後在數據庫中保存該加密串-用戶信息的對應關系,自動登錄時,用 Cookie 中的加密串,到數據庫中驗證,如果通過,自動登錄才算通過。

2.2.1 基本原理

當瀏覽器發起表單登錄請求時,當通過 UsernamePasswordAuthenticationFilter 認證成功後,會經過 RememberMeService,在其中有個 TokenRepository,它會生成一個 token,首先將 token 寫入到瀏覽器的 Cookie 中,然後將 token、認證成功的用戶名寫入到數據庫中。

當瀏覽器下次請求時,會經過 RememberMeAuthenticationFilter,它會讀取 Cookie 中的 token,交給 RememberMeService 從數據庫中查詢記錄。如果存在記錄,會讀取用戶名並去調用 UserDetailsService,獲取用戶信息,並將用戶信息放入Spring Security 中,實現自動登陸。
技術分享圖片

RememberMeAuthenticationFilter 在整個過濾器鏈中是比較靠後的位置,也就是說在傳統登錄方式都無法登錄的情況下才會使用自動登陸。
技術分享圖片

2.2.2 代碼實現

首先需要創建一張表來存儲 token 信息:

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;

在 WebSecurityConfig 中註入 dataSource ,創建一個 PersistentTokenRepository 的Bean:

@Autowired
private DataSource dataSource;

 @Bean
 public PersistentTokenRepository persistentTokenRepository(){
     JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
     tokenRepository.setDataSource(dataSource);
     // 如果token表不存在,使用下面語句可以初始化該表;若存在,請註釋掉這條語句,否則會報錯。
//        tokenRepository.setCreateTableOnStartup(true);
     return tokenRepository;
 }

config() 中按如下所示配置自動登陸:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            // 如果有允許匿名的url,填在下面
//                .antMatchers().permitAll()
            .anyRequest().authenticated()
            .and()
            // 設置登陸頁
            .formLogin().loginPage("/login")
            // 設置登陸成功頁
            .defaultSuccessUrl("/").permitAll()
            // 自定義登陸用戶名和密碼參數,默認為username和password
//                .usernameParameter("username")
//                .passwordParameter("password")
            .and()
            .logout().permitAll()
            // 自動登錄
            .and().rememberMe()
                .tokenRepository(persistentTokenRepository())
                // 有效時間:單位s
                .tokenValiditySeconds(60)
                .userDetailsService(userDetailsService);

    // 關閉CSRF跨域
    http.csrf().disable();
}

三、運行程序

勾選自動登錄後,Cookie 和數據庫中均存儲了 token 信息:

技術分享圖片


---------------------
作者:Jitwxs
來源:CSDN
原文:https://blog.csdn.net/yuanlaijike/article/details/80249869

SpringBoot集成Spring Security(2)——自動登錄