1. 概述

本教程将展示如何使用 Spring Security 在 Web 应用程序中启用和配置记住我功能。已经讨论了设置具有安全性和简单表单登录的 MVC 应用程序。

该机制将能够跨多个会话识别用户——因此首先要了解的是,Remember Me 仅在会话超时后才会启动。默认情况下,这会在 30 分钟不活动后发生,但可以在web.xml 中配置超时。

注意:本教程重点介绍标准的基于 cookie 的方法。对于持久性方法,请查看Spring Security – Persistent Remember Me指南。

2. 安全配置

让我们看看如何使用 Java 设置安全配置:

@Configuration
@EnableWebSecurity
public class SecSecurityConfig {

    @Bean
    public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
        return http.getSharedObject(AuthenticationManagerBuilder.class)
            .build();
    }

    @Bean
    public InMemoryUserDetailsManager userDetailsService() {
        UserDetails user = User.withUsername("user1")
            .password("{noop}user1Pass")
            .authorities("ROLE_USER")
            .build();
        UserDetails admin = User.withUsername("admin1")
            .password("{noop}admin1Pass")
            .authorities("ROLE_ADMIN")
            .build();
        return new InMemoryUserDetailsManager(user, admin);
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/anonymous*")
            .anonymous()
            .antMatchers("/login*")
            .permitAll()
            .anyRequest()
            .authenticated()
            .and()
            .formLogin()
            .loginPage("/login.html")
            .loginProcessingUrl("/login")
            .failureUrl("/login.html?error=true")
            .and()
            .logout()
            .deleteCookies("JSESSIONID")
            .and()
            .rememberMe()
            .key("uniqueAndSecret");
        return http.build();
    }
}

如您所见,使用rememberMe()方法的基本配置非常简单,同时通过附加选项保持非常灵活。密钥在这里很重要——它是整个应用程序的私有价值秘密,将在生成令牌内容时使用。

此外,可以使用tokenValiditySeconds()将令牌有效时间从默认的 2 周配置为 - 例如 - 一天 :

rememberMe().key("uniqueAndSecret").tokenValiditySeconds(86400)

我们还可以查看等效的 XML 配置:

<http use-expressions="true">
    <intercept-url pattern="/anonymous*" access="isAnonymous()" />
    <intercept-url pattern="/login*" access="permitAll" />
    <intercept-url pattern="/**" access="isAuthenticated()" />

    <form-login login-page='/login.html' 
      authentication-failure-url="/login.html?error=true" />
    <logout delete-cookies="JSESSIONID" />

    <remember-me key="uniqueAndSecret"/>
</http>

<authentication-manager id="authenticationManager">
    <authentication-provider>
        <user-service>
            <user name="user1" password="{noop}user1Pass" authorities="ROLE_USER" />
            <user name="admin1" password="{noop}admin1Pass" authorities="ROLE_ADMIN" />
        </user-service>
    </authentication-provider>
</authentication-manager>

3. 登录表单


<html>
<head></head>

<body>
    <h1>Login</h1>

    <form name='f' action="login" method='POST'>
        <table>
            <tr>
                <td>User:</td>
                <td><input type='text' name='username' value=''></td>
            </tr>
            <tr>
                <td>Password:</td>
                <td><input type='password' name='password' /></td>
            </tr>
            <tr>
                <td>Remember Me:</td>
                <td><input type="checkbox" name="remember-me" /></td>
            </tr>
            <tr>
                <td><input name="submit" type="submit" value="submit" /></td>
            </tr>
        </table>
    </form>

</body>
</html>

注意新添加的复选框输入——映射到remember-me。这个添加的输入足以让记住我处于活动状态。

此默认路径也可以更改如下:

.rememberMe().rememberMeParameter("remember-me-new")

4. Cookie

当用户登录时,该机制将创建一个额外的 cookie——“记住我”cookie。

Remember Me cookie包含以下数据:

  • username - 识别登录的主体
  • expirationTime – 使 cookie 过期;默认为 2 周
  • MD5 哈希 – 前 2 个值 – usernameexpirationTime,加上 密码 和预定义 密钥

这里首先要注意的是,用户名密码 都是 cookie 的一部分 — 这意味着,如果更改其中一个,cookie 将不再有效。此外,可以从 cookie 中读取 用户名

此外,重要的是要了解,如果记住我的 cookie 被捕获,此机制可能会受到攻击。cookie 将有效且可用,直到它过期或凭据被更改。

5. 在实践中

要轻松查看记住我机制的工作情况,您可以:

  • 登录并记住我
  • 等待会话过期(或删除浏览器中的JSESSIONID cookie)
  • 刷新页面

如果没有激活 remember me,在 cookie 过期后,用户应该被重定向回登录页面。在remember me的帮助下,用户现在在新的 token/cookie 的帮助下保持登录状态。

6. 结论

本教程展示了如何在安全配置中设置和配置记住我功能,并简要描述了将何种数据放入 cookie。