Spring Security – Persistent Remember Me – Spring Security – Persistent Remember Me

最后修改: 2014年 6月 4日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

This article will show how to set up the Remember Me functionality in Spring Security – using not the standard cookie only approach but a more secure solution, using persistence.

本文将展示如何在Spring Security中设置记住我的功能–不是使用标准的仅有cookie的方法,而是使用持久性的更安全的解决方案

As a quick intro – Spring can be configured to remember login details between browser sessions. This allows you to login to a website and then have it automatically log you back in the next time you visit the site (even if you have closed the browser in the meantime).

作为一个快速介绍–Spring可以被配置为在不同的浏览器会话之间记住登录细节。这允许你登录到一个网站,然后在你下次访问该网站时自动登录(即使你在此期间关闭了浏览器)。

2. Two “Remember Me” Solutions

2.两个 “记住我 “的解决方案

Spring provides two slightly different implementations to solve the problem. Both use the UsernamePasswordAuthenticationFilter, using hooks to invoke a RememberMeServices implementation.

Spring提供了两种略有不同的实现来解决这个问题。两者都使用UsernamePasswordAuthenticationFilter,使用钩子来调用RememberMeServices实现。

We already covered the standard Remember Me solution, using only a cookie, in a previous article. This solution used a cookie called remember-me – containing the username, expiration time and MD5 hash containing the password. Because it contains a hash of the password, this solution is potentially vulnerable if the cookie is captured.

我们已经在之前的文章中介绍了仅使用 cookie 的标准 “记住我 “解决方案。该解决方案使用一个名为remember-me的cookie,其中包含用户名、到期时间和包含密码的MD5哈希值。由于它包含密码的哈希值,如果该cookie被捕获,该解决方案就有可能受到攻击

With that in mind – let’s take a look at the second approach – using PersistentTokenBasedRememberMeServices to store the persisted login information in a database table between sessions.

考虑到这一点–让我们看看第二种方法–使用PersistentTokenBasedRememberMeServices在会话之间将持久化的登录信息存储在数据库表中。

3. Prerequisites – Create the Database Table

3.先决条件 – 创建数据库表

First – we need to have the login information in the database – we need a table creating to hold the data:

首先–我们需要在数据库中拥有登录信息–我们需要创建一个表来保存这些数据。

create table if not exists persistent_logins ( 
  username varchar_ignorecase(100) not null, 
  series varchar(64) primary key, 
  token varchar(64) not null, 
  last_used timestamp not null 
);

This is created automatically on startup via the following XML configuration (using an in-memory H2 db):

这是通过以下XML配置在启动时自动创建的(使用内存中的H2数据库)。

<!-- create H2 embedded database table on startup -->
<jdbc:embedded-database id="dataSource" type="H2">
    <jdbc:script location="classpath:/persisted_logins_create_table.sql"/> 
</jdbc:embedded-database>

And for the sake of completeness, here is the way persistence is set up:

为了完整起见,这里是持久性的设置方式。

@Configuration
@EnableTransactionManagement
@PropertySource({ "classpath:persistence-h2.properties" })
public class DatabaseConfig {

    @Autowired private Environment env;

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("jdbc.url"));
        dataSource.setUsername(env.getProperty("jdbc.user"));
        dataSource.setPassword(env.getProperty("jdbc.pass"));
        return dataSource;
    }
}

4. The Spring Security Configuration

4.Spring安全配置

The first key configuration is the Remember-Me Http Configuration (notice the dataSource property):

第一个关键配置是Remember-Me Http配置(注意dataSource属性)。

<http use-expressions="true">
    ...
    <remember-me data-source-ref="dataSource" token-validity-seconds="86400"/>
<http"> 

Next – we need to configure the actual RememberMeService and the JdbcTokenRepository (which also makes use of the dataSource):

接下来–我们需要配置实际的RememberMeServiceJdbcTokenRepository(它也利用了dataSource)

<!-- Persistent Remember Me Service -->
<beans:bean id="rememberMeAuthenticationProvider" class=
  "org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
    <beans:constructor-arg value="myAppKey" />
    <beans:constructor-arg ref="jdbcTokenRepository" />
    <beans:constructor-arg ref="myUserDetailsService" />
</beans:bean>
 
<!-- Uses a database table to maintain a set of persistent login data -->
<beans:bean id="jdbcTokenRepository" 
  class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl"> 
    <beans:property name="createTableOnStartup" value="false" /> 
    <beans:property name="dataSource" ref="dataSource" /> 
</beans:bean>

<!-- Authentication Manager (uses same UserDetailsService as RememberMeService)--> 
<authentication-manager alias="authenticationManager"> 
    <authentication-provider user-service-ref="myUserDetailsService"/> 
    </authentication-provider> 
</authentication-manager> 

5. The Cookie

5.饼干》

As we mentioned, the standard TokenBasedRememberMeServices was storing the hashed user password in the cookie.

正如我们所提到的,标准的TokenBasedRememberMeServices是将散列的用户密码存储在cookie中。

This solution – the PersistentTokenBasedRememberMeServices uses a unique series identifier for the user. This identifies the initial login of the user and remains constant each time the user gets logged in automatically during that persistent session. It also contains a random token that is regenerated each time a user logs in via the persisted remember-me functions.

这个解决方案–PersistentTokenBasedRememberMeServices使用一个用户的独特系列标识符。这标识了用户的初始登录,并且在该持久性会话期间,每次用户自动登录时都保持不变。它还包含一个随机令牌,在用户每次通过持久化的remember-me功能登录时都会重新生成。

This combination of randomly generated series and token are persisted, making a brute force attack very unlikely.

这种随机生成的系列和令牌的组合是持久的,使得暴力攻击的可能性非常小。

6. In Practice

6.实践中

To see the remember me mechanism working in a browser, you can:

要看到记住我的机制在浏览器中工作,你可以。

  1. Login with Remember Me active
  2. Close the browser
  3. Re-open the browser and return to the same page. Refresh.
  4. You will still be logged in

Without Remember Me active, after the cookie expires the user should be redirected back to the login page. With remember me, the user now stays logged in with the help of the new token/cookie.

如果没有激活记住我,在cookie过期后,用户应该被重定向到登录页面。使用记住我,用户现在会在新的令牌/cookie的帮助下保持登录状态。

You can also view the cookies in the browser, and the persisted data in the database (note – you may want to switch from the embedded H2 implementation for this).

你还可以查看浏览器中的cookies,以及数据库中的持久数据(注意–你可能想为此从嵌入式H2实现中切换出来)。

7. Conclusion

7.结论

This tutorial illustrated how to set up and configure a database persisted Remember Me Token functionality. It is also a follow-up to the previous article which discussed the standard Cookie Token-based functionality. The Database approach is more secure as password details are not persisted in the cookie – but it does involve slightly more configuration.

本教程说明了如何设置和配置数据库持久化的Remember Me Token功能。它也是前一篇文章的后续,前一篇文章讨论了标准的基于 Cookie 的令牌功能。数据库方法更加安全,因为密码的详细信息不会持续存在于cookie中 – 但它确实涉及稍多的配置。

The implementation of this Spring Security REST Tutorial can be found in the GitHub project – this is an Eclipse-based project, so it should be easy to import and run as it is.

这个Spring Security REST教程的实现可以在GitHub项目中找到 – 这是一个基于Eclipse的项目,因此应该很容易导入并按原样运行。