Spring Session and Spring Security
本指南介绍如何将 Spring 会话与 Spring 安全性结合使用。它假定您已经将 Spring 安全性应用于您的应用程序了。
你可以从security sample application中找到已完成的指南。 |
Updating Dependencies
在使用 Spring 会话之前,您必须更新依赖。如果您使用 Maven,您必须添加以下依赖:
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>{spring-session-version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>{lettuce-core-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>{spring-core-version}</version>
</dependency>
</dependencies>
Spring Configuration
在添加所需的依赖项后,我们可以创建我们的 Spring 配置。Spring 配置负责创建一个 Servlet 过滤器,该过滤器将 HttpSession
实现替换为由 Spring Session 支持的实现。为此,请添加以下 Spring 配置:
Unresolved include directive in modules/ROOT/pages/guides/java-security.adoc - include::example$spring-session-samples/spring-session-sample-javaconfig-security/src/main/java/sample/Config.java[]
1 | @EnableRedisHttpSession 注释会创建一个 Spring bean,其名称为 springSessionRepositoryFilter`并会实现 `Filter 。该筛选器负责替换 HttpSession 实现,以便由 Spring Session 支持。在这种情况中,Spring Session 由 Redis 支持。 |
2 | 我们创建一个 RedisConnectionFactory ,将 Spring 会话连接到 Redis 服务器。我们配置连接以在默认端口 (6379) 上连接到 localhost。有关配置 Spring 数据 Redis 的更多信息,请参阅 {docs-url}/spring-data/data-redis/docs/{spring-data-redis-version}/reference/html/[参考文档]。 |
Servlet Container Initialization
我们的 Spring Configuration 创建了一个名为 springSessionRepositoryFilter
的 Spring bean,它实现了 Filter
。springSessionRepositoryFilter
bean 负责使用由 Spring 会话支持的自定义实现替换 HttpSession
。
为了让我们的 Filter`发挥作用,Spring 需要加载我们的 `Config
类。由于我们的应用程序已通过使用 SecurityInitializer
类加载了 Spring 配置,因此我们可将配置类添加到其中。以下示例说明了如何进行此操作:
Unresolved include directive in modules/ROOT/pages/guides/java-security.adoc - include::example$spring-session-samples/spring-session-sample-javaconfig-security/src/main/java/sample/SecurityInitializer.java[]
最后,我们需要确保 Servlet 容器(即 Tomcat)为每个请求使用我们的 springSessionRepositoryFilter
。非常重要的是,Spring 会话的 springSessionRepositoryFilter
要在 Spring 安全性的 springSecurityFilterChain
之前调用。这确保了 Spring 安全性使用的 HttpSession
由 Spring 会话支持。幸运的是,Spring 会话提供了一个称为 AbstractHttpSessionApplicationInitializer
的实用类程序,使得此操作变得容易。以下示例说明了如何进行此操作:
Unresolved include directive in modules/ROOT/pages/guides/java-security.adoc - include::example$spring-session-samples/spring-session-sample-javaconfig-security/src/main/java/sample/Initializer.java[]
我们的类 (Initializer) 的名称并不重要,重要的是我们必须延伸`AbstractHttpSessionApplicationInitializer`。 |
通过扩展 AbstractHttpSessionApplicationInitializer
,我们可以确保名为 springSessionRepositoryFilter
的 Spring Bean 在 Spring 安全性的 springSecurityFilterChain
之前为每个请求向我们的 Servlet 容器注册。
security
Sample Application
本节介绍如何使用 security
示例应用程序。
Running the security
Sample Application
您可以获取 源代码 并调用以下命令运行示例:
$ ./gradlew :spring-session-sample-javaconfig-security:tomcatRun
要让示例发挥作用,你必须在 localhost 上 install Redis 2.8+ 并使用默认端口 (6379) 运行它。或者,你可以更新 |
您现在应该能够访问 [role="bare"][role="bare"]http://localhost:8080/ 中的应用程序。
Exploring the security
Sample Application
现在,您可以使用该应用程序了。输入以下内容来登录:
-
Username user
-
Password password
然后,请点击 Login 按钮。您现在应该会看到一条消息,提示您已使用之前输入的用户登录了。此用户的详细信息存储在 Redis 中,而不是在 Tomcat 的 HttpSession
实现中。
How Does It Work?
我们不使用 Tomcat 的 HttpSession
,而将值存储在 Redis 中。Spring 会话使用由 Redis 支持的实现替换 HttpSession
。当 Spring 安全性的 SecurityContextPersistenceFilter
将 SecurityContext
保存到 HttpSession
中时,其随后将存储在 Redis 中。
当创建新的 HttpSession
时,Spring Session 在浏览器中创建一个名为 SESSION
的 cookie。该 cookie 包含会话 ID。您可以查看 cookie(使用 Chrome 或 Firefox)。
您可以使用 redis-cli 删除该会话。例如,在基于 Linux 的系统中,您可以键入以下命令:
$ redis-cli keys '*' | xargs redis-cli del
Redis 文档包含有关 installing redis-cli 的说明。 |
或者,您还可以删除显式键。将以下命令输入到您的终端中,并确保使用 SESSION
cookie 的值替换 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
:
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
现在,您可以访问 [role="bare"][role="bare"]http://localhost:8080/ 中的应用程序并看到我们不再通过身份验证。