1. 程式人生 > 實用技巧 >認證和授權學習4:springboot+springsecurity實現記住我下次自動登入的功能

認證和授權學習4:springboot+springsecurity實現記住我下次自動登入的功能

認證和授權學習4:springboot+springsecurity實現記住我下次自動登入的功能

本文使用的springboot版本是22.1.3.RELEASE

[上一篇:springsecurity實現方法級的許可權控制](https://www.cnblogs.com/chengxuxiaoyuan/p/13973495.html)

目錄

一、原理分析

第一次登陸時,如果使用者勾選了readme選項,登陸成功後springsecurity會生成一個cookie,返回給瀏覽器端,並且在服務端生成一個登入成功的標識token和這個cookie繫結,待登入失效後,瀏覽器下次訪問時如果攜帶了這個cookie,springsecurity如果根據cookie能夠查詢到登入成功的token,就放行這次登入。

二、工程依賴

<!-- 以下是>spring boot依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 以下是>spring security依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <!--資料庫相關-->
        <!--資料庫驅動-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.32</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.11</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

三、登入頁面

<form action="login" method="post">
    使用者名稱:<input type="text" name="username"><br>
    密&nbsp;&nbsp;&nbsp;碼:
    <input type="password" name="password"><br>
    <input type="checkbox" name="remembermeParamater" value="true">記住我
    <input type="submit" value="登入">
</form>

頁面上增加一個checkbox表示記住我,向服務端傳遞true或者false,name要和後端指定的引數名保持一致。

四、服務端簡單實現,把token放在記憶體中

在springsecurity的配置類中配置使用remember

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)//開啟方法許可權控制
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    //使用者配置
    ...
    //安全配置
        http.csrf().disable();
        //匹配路徑時越具體的路徑要先匹配
        http.authorizeRequests().anyRequest().permitAll();
        //注意自定義安全配置時一定要把登入頁面和登入url配上,不然訪問任何頁面都是403,除非最後一行呼叫父類的config方法
        http.formLogin().loginPage("/login.html").loginProcessingUrl("/login");
        http.rememberMe().rememberMeParameter("remembermeParamater")
        http.rememberMe().tokenValiditySeconds(60*2);//有效時間,已秒為單位
}

注意這裡這個rememberMeParameter方法指定的引數要和登入頁面上保持一致。

這樣當用戶第一次登入成功後,關閉瀏覽器,開啟瀏覽器再次訪問系統,即可直接登入成功,但這種實現方式,因為服務端生成的token是儲存在記憶體中的,所以服務端重啟後用戶的記住我資料就會失效。

五、持久化儲存token實現

在資料庫中建立一張表,用來儲存token,這張表的欄位是springsecurity指定的

-- 建立記錄rememberme記錄的表
CREATE TABLE persistent_logins
(
  username  VARCHAR(64),
  series   VARCHAR(64),
  token     VARCHAR(64),
  last_used DATETIME
 );

針對上邊簡單實現的缺陷,可以配置讓springsecurity把使用者登入後生成的記住我token儲存在資料庫中。這種方式需要指定tokenRepository


@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)//開啟方法許可權控制
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
     //使用者配置
    ...
    //安全配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        //匹配路徑時越具體的路徑要先匹配
        http.authorizeRequests().anyRequest().permitAll();
        //注意自定義安全配置時一定要把登入頁面和登入url配上,不然訪問任何頁面都是403,除非最後一行呼叫父類的config方法
        http.formLogin().loginPage("/login.html").loginProcessingUrl("/login");
        http.rememberMe().rememberMeParameter("remembermeParamater").tokenRepository(persistentTokenRepository);
        http.rememberMe().tokenValiditySeconds(60*2);//有效時間,已秒為單位
    }

    @Autowired
    private DataSource dataSource;

    @Autowired
    private PersistentTokenRepository persistentTokenRepository;
    
    @Bean
    public PersistentTokenRepository persistentTokenRepository(@Qualifier("dataSource") DataSource dataSource) {
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource); // 設定資料來源
        tokenRepository.setCreateTableOnStartup(false); // 不讓自動建立表
        return tokenRepository;
    }
}

這裡建立了一個PersistentTokenRepository的bean,注入給springsecurity的rememberme模組。對於PersistentTokenRepository介面,springsecurity提供了一個基於記憶體的實現和基於jdbc的實現,這裡使用的是基於jdbc的實現來把token持久化到資料庫中,所以工程中引入了jdbc的依賴。

六、總結

springboot+springsecuri實現記住我功能的原理就是第一次登陸成功後生成一個標識儲存在服務端,並且和傳送給客戶端的cookie繫結,客戶端下次訪問時查詢這個標識。標識可以儲存在記憶體中,也可以儲存在資料庫中。

完整的示例工程

示例工程