Spring Seucrity的Remember Me机制(二)

Tags: java spring

Spring Seucrity的Remember Me机制(二)

id: 119979
url:http://www.baeldung.com/spring-security-persistent-remember-me

1. Overview

这篇文章将介绍如何设置Spring SecurityRemember-me功能 -- 不使用标准 cookie的方法,但是更安全的解决方(使用持久层)。

快速介绍 — — Spring可以配置用来保持浏览器会话间的登录信息。这允许您登录到一个网站时记录你的登录信息,下次访问时无需再次登录(即使在此期间关闭了浏览器)。

2. 两种"Remember Me"解决方案

Spring提供两种截然不同的方式解决这个问题。他们都使用UsernamePasswordAuthenticationFilter这个过滤器,使用hooks调用一个RememberMeServices的实现。

我们已经在http://www.4byte.cn/learning/119969/spring-seucrity-de-remember-me-ji-zhi-yi.html这边文章中介绍了标准的使用Cookie的Remember-me解决方案。这个方案使用一个名为SPRING_SECURITY_REMEMBER_ME_COOKIE的cookie来保存用户名、超时时间和MD5加密的密码。由于Cookie中保存了密码的hash值,因此如果Cookie被捕获,这个解决方案是潜在易受攻击。

3.系统必备组件-创建数据库表

首先,我们需要保存登录信息到数据库中,我们需要创建一个表来保存数据:

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
);

使用下面的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>

并且出于完整性的考虑,下面是持久层的设置代码:

@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. 配置Spring Security

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

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

然后,我们需要配置当前要用的RememberMeServiceJdbcTokenRepository(也将使用dataSource)

<!-- Persistent Remember Me Service -->
<beans:bean id="rememberMeAuthenticationProvider" class=
  "org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
    <beans:property name="key" value="myAppKey" />
    <beans:property name="tokenRepository" ref="jdbcTokenRepository" />
    <beans:property name="userDetailsService" 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. Cookie

正如我们所提到的标准的TokenBasedRememberMeServices在cookie 中存储用户密码的hash(MD5)值。

在这个解决方案中 -- PersistentTokenBasedRememberMeServices为每个用户提供了一个单独的令牌。这令牌在用户初次登录是自动生成,并且用户在该持久性会话期间能够保持不变。它还包含一个随机的令牌,在用户每次通过持久化Remember-Me功能登录时自动生成。

组合使用随机生成令牌和持久化令牌的方式,是的被暴力破解的几率相对较小。

6. 实践

要在浏览器中查看看Remember-me功能是否工作,可以:

  1. 登录系统使得Remember-me开始工作

  2. 关闭浏览器

  3. 打开浏览器并重新打开刚才的页面

  4. 你应该还处于登录状态

  5. 如果Remember-me功能没有正常工作:

    当Cookie失效后用户再打开页面时会跳转到登录页

  6. 如果Remember-me功能正常工作:

    用户会使用包含新生成令牌的Cookie登录系统。

7. 结论

这边文章继http://www.4byte.cn/learning/119969/spring-seucrity-de-remember-me-ji-zhi-yi.html之后,介绍了如何配置Spring Security的Remember-me功能。使用数据库更加安全,并且不会在Cookie中保存密码(MD5加密的),但是完成这个工作这需要比第一篇文章中更多的配置。

这篇文章的实现项目已经托管在GitHub上,是一个Eclipse项目,所以应该很容易导入和运行。


来源:Spring Security – Persistent Remember Me
翻译:4byte.cn

本文链接:http://www.4byte.cn/learning/119979/spring-seucrity-de-remember-me-ji-zhi-er.html