Fork me on GitHub
余鸢

Spring Session-REST

本指南介绍如何使用Spring Session在使用REST端点时透明地利用Redis来回退Web应用程序的HttpSession。

完成的指南可以在rest sample application中找到。

Updating Dependencies

在使用Spring Session之前,必须确保更新依赖项。 如果您使用Maven,请确保添加以下依赖项:

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>1.3.0.RELEASE</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>biz.paluch.redis</groupId>
<artifactId>lettuce</artifactId>
<version>3.5.0.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.4.RELEASE</version>
</dependency>
</dependencies>

Spring Configuration

添加所需的依赖项后,我们可以创建我们的Spring配置。 Spring配置负责创建一个Servlet过滤器,它用Spring Session支持的实现替换HttpSession实现。 添加以下Spring配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Configuration
@EnableRedisHttpSession
public class HttpSessionConfig {
@Bean
public LettuceConnectionFactory connectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
public HttpSessionStrategy httpSessionStrategy() {
return new HeaderHttpSessionStrategy();
}
}

@EnableRedisHttpSession注释创建一个名为springSessionRepositoryFilter的Spring Bean,它实现了Filter。 过滤器是负责替换HttpSession实现由Spring会话支持。 在这个例子中,Spring Session由Redis支持。

我们创建一个RedisConnectionFactory,将Spring Session连接到Redis服务器。 我们配置连接以连接到默认端口(6379)上的localhost有关配置Spring Data Redis的更多信息,请参考reference documentation

我们定制Spring Session的HttpSession集成,使用HTTP头来传达当前会话信息,而不是Cookie。

Servlet容器初始化

我们的Spring Configuration创建了一个Spring Bean,名为springSessionRepositoryFilter,它实现了FilterspringSessionRepositoryFilter bean负责用Spring Session支持的自定义实现替换HttpSession

为了使我们的Filter能够做到这一点,Spring需要加载我们的Config类。 我们在Spring MvcInitializer中提供配置如下所示:

src/main/java/sample/mvc/MvcInitializer.java

1
2
3
4
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { SecurityConfig.class, HttpSessionConfig.class };
}

最后,我们需要确保我们的Servlet容器(即Tomcat)对于每个请求使用我们的springSessionRepositoryFilter。 幸运的是,Spring Session提供了一个名为AbstractHttpSessionApplicationInitializer的实用程序类,使其非常容易。 只需使用默认构造函数扩展类,如下所示:

src/main/java/sample/Initializer.java

1
2
3
public class Initializer extends AbstractHttpSessionApplicationInitializer {
}

我们的类的名字(Initializer)没关系。 重要的是我们扩展AbstractHttpSessionApplicationInitializer。

rest示例应用程序

运行rest 样本应用程序

您可以通过获取 source code并调用以下命令来运行示例:

要使样本工作,必须在localhost上安装install Redis 2.8+,并使用默认端口(6379)运行它。 或者,您可以更新LettuceConnectionFactory以指向Redis服务器。

1
$ ./gradlew :samples:rest:tomcatRun

探索rest 样本应用程序

尝试使用应用程序。 使用你最喜欢的REST客户端请求http://localhost:8080/

1
$ curl -v http://localhost:8080/

观察到我们被提示进行基本认证。 提供用户名和密码的以下信息:

  • Username user
  • Password password

$ curl -v http://localhost:8080/ -u user:password

在输出中,您将注意到以下内容:

1
2
3
4
5
HTTP/1.1 200 OK
...
x-auth-token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3
{"username":"user"}

具体来说,我们注意到以下有关我们的反应:

  • HTTP状态现在为200
  • 我们有一个包含x-auth-token名称的头,它包含一个新的会话id

  • 显示当前用户名

我们现在可以使用x-auth-token再次提供另一个请求,而不再提供用户名和密码。 例如,以下输出用户名与之前一样:

1
$ curl -v http://localhost:8080/ -H "x-auth-token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"

唯一的区别是,响应头中没有提供会话ID,因为我们正在重用现有会话。

如果我们使会话无效,则x-auth-token在响应中显示为空值。 例如,以下将使会话无效:

1
$ curl -v http://localhost:8080/logout -H "x-auth-token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"

您将在输出中看到x-auth-token提供了一个空字符串,表示前一个会话已失效。

1
2
3
HTTP/1.1 204 No Content
...
x-auth-token:

How does it work?

Spring Security与SecurityContextPersistenceFilter中的标准HttpSession交互。

Spring Security现在不是使用Tomcat的HttpSession,而是将值保存在Redis中。 Spring会在您的浏览器中创建一个名为x-auth-token的头,它包含会话的id。

如果你喜欢,你可以很容易地看到会话是在Redis中创建的。 首先使用以下命令创建会话:

$ curl -v http://localhost:8080/ -u user:password

在输出中,您将注意到以下内容:

1
2
3
4
5
HTTP/1.1 200 OK
...
x-auth-token: 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
{"username":"user"}

现在使用redis-cli删除会话。 例如,在基于Linux的系统上,您可以输入:

1
$ redis-cli keys '*' | xargs redis-cli del

Redis文档中有关于installing redis-cli的说明。

或者,你也可以删除显式键。 在终端输入以下内容,确保用您的SESSION cookie的值替换7e8383a4-082c-4ffe-a4bc-c40fd3363c5e

1
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e

我们现在可以使用x-auth-token来向我们删除的会话发出另一个请求,并观察我们是否被提示进行身份验证。 例如,以下内容返回HTTP 401:

1
$ curl -v http://localhost:8080/ -H "x-auth-token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"

注:翻译自

http://docs.spring.io/spring-session/docs/current/reference/html5/guides/rest.html