HttpSession
Integration
Spring Session 与 HttpSession
提供透明集成。这意味着开发人员可以将 HttpSession
实现替换为由 Spring Session 支持的实现。
Spring Session provides transparent integration with HttpSession
.
This means that developers can switch the HttpSession
implementation out with an implementation that is backed by Spring Session.
Why Spring Session and HttpSession
?
我们已经提到 Spring Session 与 HttpSession
提供透明集成,但我们从中获得了哪些好处?
We have already mentioned that Spring Session provides transparent integration with HttpSession
, but what benefits do we get out of this?
-
Clustered Sessions: Spring Session makes it trivial to support httpsession-redis without being tied to an application container specific solution.
-
RESTful APIs: Spring Session lets providing session IDs in headers work with httpsession-rest
HttpSession
with Redis
在 HttpSession
中使用 Spring Session 是通过在所有使用 HttpSession
的内容之前添加 Servlet Filter 来实现的。您可以选择通过使用以下任一种方式来启用此功能:
Using Spring Session with HttpSession
is enabled by adding a Servlet Filter before anything that uses the HttpSession
.
You can choose from enabling this by using either:
Redis Java-based Configuration
本节介绍如何使用基于 Java 的配置通过 Redis 来支持 HttpSession
。
This section describes how to use Redis to back HttpSession
by using Java based configuration.
HttpSession Sample 提供了一个关于如何通过 Java 配置整合 Spring Session 和 |
The HttpSession Sample provides a working sample of how to integrate Spring Session and |
@11
Spring Session - HttpSession (Quick Start)
Rob Winch
本指南描述了如何使用 Spring Session 透明地利用 Redis 为 Web 应用程序的`HttpSession`提供支持,采用的是 Java 配置。
This guide describes how to use Spring Session to transparently leverage Redis to back a web application’s HttpSession
with Java Configuration.
您可以在httpsession sample application中找到已完成指南。 |
You can find the completed guide in the httpsession-sample. |
Updating Dependencies
在你使用 Spring Session 之前,你必须更新你的依赖项。如果你使用的是 Maven,你必须添加以下依赖项:
Before you use Spring Session, you must update your dependencies. If you are using Maven, you must add the following dependencies:
<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>
由于我们使用的是 SNAPSHOT 版本,因此我们需要确保添加 Spring Snapshot Maven 存储库。在你的 pom.xml 中必须具有以下内容:
Since we are using a SNAPSHOT version, we need to ensure to add the Spring Snapshot Maven Repository. You must have the following in your pom.xml:
<repositories>
<!-- ... -->
<repository>
<id>spring-snapshot</id>
<url>https://repo.spring.io/libs-snapshot</url>
</repository>
</repositories>
Spring Java Configuration
在添加所需的依赖项后,我们可以创建我们的 Spring 配置。Spring 配置负责创建一个 Servlet 过滤器,该过滤器将 HttpSession
实现替换为由 Spring Session 支持的实现。为此,请添加以下 Spring 配置:
After adding the required dependencies, we can create our Spring configuration.
The Spring configuration is responsible for creating a servlet filter that replaces the HttpSession
implementation with an implementation backed by Spring Session.
To do so, add the following Spring Configuration:
Unresolved include directive in modules/ROOT/pages/guides/java-redis.adoc - include::example$spring-session-samples/spring-session-sample-javaconfig-redis/src/main/java/sample/Config.java[]
1 | The @EnableRedisHttpSession annotation creates a Spring Bean with the name of springSessionRepositoryFilter that implements Filter .
The filter is in charge of replacing the HttpSession implementation to be backed by Spring Session.
In this instance, Spring Session is backed by Redis. |
2 | We create a RedisConnectionFactory that connects Spring Session to the Redis Server.
We configure the connection to connect to localhost on the default port (6379).
For more information on configuring Spring Data Redis, see the {docs-url}/spring-data/data-redis/docs/{spring-data-redis-version}/reference/html/[reference documentation]. |
Java Servlet Container Initialization
我们的 Spring Configuration 创建了一个名为 springSessionRepositoryFilter
的 Spring Bean,它实现了 Filter
。springSessionRepositoryFilter
Bean 负责使用由 Spring Session 支持的自定义实现来替换 HttpSession
。
Our httpsession-spring-configuration created a Spring Bean named springSessionRepositoryFilter
that implements Filter
.
The springSessionRepositoryFilter
bean is responsible for replacing the HttpSession
with a custom implementation that is backed by Spring Session.
为了让我们的 Filter
发挥作用,Spring 需要加载我们的 Config
类。最后,我们需要确保我们的 Servlet 容器(即 Tomcat)对每个请求使用我们的 springSessionRepositoryFilter
。幸运的是,Spring Session 提供了一个名为 AbstractHttpSessionApplicationInitializer
的实用程序类,可以轻松完成这两个步骤。以下显示了一个示例:
In order for our Filter
to do its magic, Spring needs to load our Config
class.
Last, we need to ensure that our Servlet Container (that is, Tomcat) uses our springSessionRepositoryFilter
for every request.
Fortunately, Spring Session provides a utility class named AbstractHttpSessionApplicationInitializer
to make both of these steps easy.
The following shows an example:
Unresolved include directive in modules/ROOT/pages/guides/java-redis.adoc - include::example$spring-session-samples/spring-session-sample-javaconfig-redis/src/main/java/sample/Initializer.java[]
我们的类 (Initializer
) 的名称并不重要,重要的是我们必须延伸`AbstractHttpSessionApplicationInitializer`。
The name of our class (Initializer
) does not matter. What is important is that we extend AbstractHttpSessionApplicationInitializer
.
1 | The first step is to extend AbstractHttpSessionApplicationInitializer .
Doing so ensures that the Spring Bean by the name of springSessionRepositoryFilter is registered with our Servlet Container for every request. |
2 | AbstractHttpSessionApplicationInitializer also provides a mechanism to ensure Spring loads our Config . |
httpsession Sample Application
Running the httpsession
Sample Application
您可以获取 源代码 并调用以下命令运行示例:
You can run the sample by obtaining the source code and invoking the following command:
$ ./gradlew :spring-session-sample-javaconfig-redis:tomcatRun
要让示例发挥作用,你必须在 localhost 上 install Redis 2.8+ 并使用默认端口 (6379) 运行它。或者,你可以更新 |
For the sample to work, you must install Redis 2.8+ on localhost and run it with the default port (6379).
Alternatively, you can update the |
您现在应该能够访问 [role="bare"][role="bare"]http://localhost:8080/ 中的应用程序。
You should now be able to access the application at [role="bare"]http://localhost:8080/
Exploring the httpsession
Sample Application
现在,你可以尝试使用该应用程序。为此,请使用以下信息填写表单:
Now you can try to use the application. To do so, fill out the form with the following information:
-
Attribute Name: username
-
Attribute Value: rob
然后,请点击 Set Attribute 按钮。您现在应该可以看到表中显示的值了。
Now click the Set Attribute button. You should now see the values displayed in the table.
How Does It Work?
我们与 HttpSession
中显示的标准 SessionServlet
进行交互,这在下表中有所说明:
We interact with the standard HttpSession
in the SessionServlet
shown in the following listing:
Unresolved include directive in modules/ROOT/pages/guides/java-redis.adoc - include::example$spring-session-samples/spring-session-sample-javaconfig-redis/src/main/java/sample/SessionServlet.java[]
我们不使用 Tomcat 的 HttpSession
,而是将值保存在 Redis 中。Spring Session 在浏览器中创建一个名为 SESSION
的 cookie。该 cookie 包含会话 ID。您可以查看 cookie(使用 Chrome 或 Firefox)。
Instead of using Tomcat’s HttpSession
, we persist the values in Redis.
Spring Session creates a cookie named SESSION
in your browser.
That cookie contains the ID of your session.
You can view the cookies (with Chrome or Firefox).
你可以使用 redis-cli 删除会话。例如,在基于 Linux 的系统上,你可以输入以下内容:
You can remove the session by using redis-cli. For example, on a Linux based system you can type the following:
$ redis-cli keys '*' | xargs redis-cli del
Redis 文档包含有关 installing redis-cli 的说明。 |
The Redis documentation has instructions for installing redis-cli. |
或者,你还可以删除显式密钥。在你的终端中输入以下内容,请务必用你的 SESSION Cookie 的值替换`7e8383a4-082c-4ffe-a4bc-c40fd3363c5e`:
Alternatively, you can also delete the explicit key. Enter the following into your terminal, being sure to replace 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
with the value of your SESSION cookie:
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
现在,您可以访问 [role="bare"][role="bare"]http://localhost:8080/ 中的应用程序并看到我们添加的属性不再显示。
Now you can visit the application at [role="bare"]http://localhost:8080/ and see that the attribute we added is no longer displayed.
Redis XML-based Configuration
本节介绍如何使用基于 XML 的配置通过 Redis 来支持 HttpSession
。
This section describes how to use Redis to back HttpSession
by using XML based configuration.
HttpSession XML Sample 提供了一个关于如何通过 XML 配置整合 Spring Session 和 |
The HttpSession XML Sample provides a working sample of how to integrate Spring Session and |
@12
Spring Session - HttpSession (Quick Start)
Rob Winch
本指南描述了如何使用 Spring 会话以透明的方式利用 Redis 来支持基于 XML 配置的 Web 应用程序的 HttpSession
。
This guide describes how to use Spring Session to transparently leverage Redis to back a web application’s HttpSession
with XML-based configuration.
您可以在 httpsession-xml sample application 中找到完整指南。 |
You can find the completed guide in the httpsession-xml-sample. |
Updating Dependencies
在使用 Spring 会话之前,您必须更新依赖。如果您使用 Maven,您必须添加以下依赖:
Before you use Spring Session, you must update your dependencies. If you use Maven, you must add the following dependencies:
<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 XML Configuration
在添加所需的依赖项后,我们可以创建我们的 Spring 配置。Spring 配置负责创建一个 Servlet 过滤器,该过滤器将 HttpSession
实现替换为由 Spring Session 支持的实现。为此,请添加以下 Spring 配置:
After adding the required dependencies, we can create our Spring configuration.
The Spring configuration is responsible for creating a servlet filter that replaces the HttpSession
implementation with an implementation backed by Spring Session.
To do so, add the following Spring Configuration:
Unresolved include directive in modules/ROOT/pages/guides/xml-redis.adoc - include::example$spring-session-samples/spring-session-sample-xml-redis/src/main/webapp/WEB-INF/spring/session.xml[]
1 | We use the combination of <context:annotation-config/> and RedisHttpSessionConfiguration because Spring Session does not yet provide XML Namespace support (see gh-104).
This creates a Spring Bean with the name of springSessionRepositoryFilter that implements Filter .
The filter is in charge of replacing the HttpSession implementation to be backed by Spring Session.
In this instance, Spring Session is backed by Redis. |
2 | We create a RedisConnectionFactory that connects Spring Session to the Redis Server.
We configure the connection to connect to localhost on the default port (6379)
For more information on configuring Spring Data Redis, see the {docs-url}/spring-data/data-redis/docs/{spring-data-redis-version}/reference/html/[reference documentation]. |
XML Servlet Container Initialization
我们的 Spring Configuration 创建了一个名为 springSessionRepositoryFilter
的 Spring Bean,它实现了 Filter
。springSessionRepositoryFilter
Bean 负责使用由 Spring Session 支持的自定义实现来替换 HttpSession
。
Our httpsession-xml-spring-configuration created a Spring Bean named springSessionRepositoryFilter
that implements Filter
.
The springSessionRepositoryFilter
bean is responsible for replacing the HttpSession
with a custom implementation that is backed by Spring Session.
为了让我们的 Filter
发挥作用,我们需要指示 Spring 加载我们的 session.xml
配置。我们可以通过以下配置来实现:
In order for our Filter
to do its magic, we need to instruct Spring to load our session.xml
configuration.
We can do so with the following configuration:
Unresolved include directive in modules/ROOT/pages/guides/xml-redis.adoc - include::example$spring-session-samples/spring-session-sample-xml-redis/src/main/webapp/WEB-INF/web.xml[]
Unresolved include directive in modules/ROOT/pages/guides/xml-redis.adoc - include::example$spring-session-samples/spring-session-sample-xml-redis/src/main/webapp/WEB-INF/web.xml[]
{docs-url}/spring/docs/{spring-core-version}/spring-framework-reference/core.html#context-create[ContextLoaderListener
] 读入 contextConfigLocation,并拾取到我们的 session.xml 配置。
The {docs-url}/spring/docs/{spring-core-version}/spring-framework-reference/core.html#context-create[ContextLoaderListener
] reads the contextConfigLocation and picks up our session.xml configuration.
最后,我们需要确保我们的 Servlet 容器(即 Tomcat)针对每个请求使用我们的 springSessionRepositoryFilter
。以下代码段为我们执行最后一步:
Last, we need to ensure that our Servlet Container (that is, Tomcat) uses our springSessionRepositoryFilter
for every request.
The following snippet performs this last step for us:
Unresolved include directive in modules/ROOT/pages/guides/xml-redis.adoc - include::example$spring-session-samples/spring-session-sample-xml-redis/src/main/webapp/WEB-INF/web.xml[]
{docs-url}/spring-framework/docs/{spring-core-version}/javadoc-api/org/springframework/web/filter/DelegatingFilterProxy.html[DelegatingFilterProxy
] 按名称查找一个 Bean springSessionRepositoryFilter
,并将其转换为 Filter
。对于调用 DelegatingFilterProxy`的每个请求,都调用 `springSessionRepositoryFilter
。
The {docs-url}/spring-framework/docs/{spring-core-version}/javadoc-api/org/springframework/web/filter/DelegatingFilterProxy.html[DelegatingFilterProxy
] looks up a Bean by the name of springSessionRepositoryFilter
and cast it to a Filter
.
For every request that DelegatingFilterProxy
is invoked, the springSessionRepositoryFilter
is invoked.
httpsession-xml
Sample Application
本节介绍如何使用 httpsession-xml
示例应用程序。
This section describes how to work with the httpsession-xml
sample application.
Running the httpsession-xml
Sample Application
您可以获取 源代码 并调用以下命令运行示例:
You can run the sample by obtaining the source code and invoking the following command:
要让示例发挥作用,你必须在 localhost 上 install Redis 2.8+ 并使用默认端口 (6379) 运行它。或者,你可以更新 |
For the sample to work, you must install Redis 2.8+ on localhost and run it with the default port (6379).
Alternatively, you can update the |
$ ./gradlew :spring-session-sample-xml-redis:tomcatRun
您现在应该能够访问 [role="bare"][role="bare"]http://localhost:8080/ 中的应用程序。
You should now be able to access the application at [role="bare"]http://localhost:8080/
Exploring the httpsession-xml
Sample Application
现在,您可以尝试使用该应用程序了。使用以下信息填写表单:
Now you can try using the application. Fill out the form with the following information:
-
Attribute Name: username
-
Attribute Value: rob
然后,请点击 Set Attribute 按钮。您现在应该可以看到表中显示的值了。
Now click the Set Attribute button. You should now see the values displayed in the table.
How Does It Work?
我们与 HttpSession
中显示的标准 SessionServlet
进行交互,这在下表中有所说明:
We interact with the standard HttpSession
in the SessionServlet
shown in the following listing:
Unresolved include directive in modules/ROOT/pages/guides/xml-redis.adoc - include::example$spring-session-samples/spring-session-sample-xml-redis/src/main/java/sample/SessionServlet.java[]
我们不使用 Tomcat 的 HttpSession
,而是将值保存在 Redis 中。Spring Session 在浏览器中创建一个名为 SESSION 的 cookie。该 cookie 包含会话 ID。您可以查看 cookie(使用 Chrome 或 Firefox)。
Instead of using Tomcat’s HttpSession
, we persist the values in Redis.
Spring Session creates a cookie named SESSION in your browser.
That cookie contains the ID of your session.
You can view the cookies (with Chrome or Firefox).
您可以使用 redis-cli 删除该会话。例如,在基于 Linux 的系统中,您可以键入以下内容:
You can remove the session using redis-cli. For example, on a Linux based system you can type the following:
$ redis-cli keys '*' | xargs redis-cli del
Redis 文档包含有关 installing redis-cli 的说明。 |
The Redis documentation has instructions for installing redis-cli. |
或者,您也可以删除显式键。为此,将以下内容输入到您的终端中,并确保使用 SESSION cookie 的值替换 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
:
Alternatively, you can also delete the explicit key. To do so, enter the following into your terminal, being sure to replace 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
with the value of your SESSION cookie:
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
现在,您可以访问 [role="bare"][role="bare"]http://localhost:8080/ 中的应用程序并看到我们添加的属性不再显示。
Now you can visit the application at [role="bare"]http://localhost:8080/ and see that the attribute we added is no longer displayed.
HttpSession with Mongo
使用 `HttpSession`的 Spring Session 可通过在使用 `HttpSession`的任何内容之前添加一个 Servlet 过滤器来启用。
Using Spring Session with HttpSession
is enabled by adding a Servlet Filter before anything that uses the HttpSession
.
本部分介绍如何使用 Mongo 来基于 Java 配置支持 HttpSession
。
This section describes how to use Mongo to back HttpSession
using Java based configuration.
HttpSession Mongo Sample 提供了一个使用 Java 配置集成 Spring Session 和 |
The samples provides a working sample on how to integrate Spring Session and |
@13
Spring Session - MongoDB Repositories
Jakub Kubrynski, Greg Turnquist
本指南介绍了如何使用基于 MongoDB 的 Spring Session。
This guide describes how to use Spring Session backed by MongoDB.
已完成的指南可在 mongo sample application 中找到。 |
The completed guide can be found in the mongo-sample. |
Updating Dependencies
在使用 Spring Session MongoDB 前,您必须确保更新您的依赖项。我们假设您正在使用可正常运行的 Spring Boot Web 应用程序。如果您使用的是 Maven,确保添加以下依赖项:
Before you use Spring Session MongoDB, you must ensure to update your dependencies. We assume you are working with a working Spring Boot web application. If you are using Maven, ensure to add the following dependencies:
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-mongodb</artifactId>
</dependency>
</dependencies>
Spring Configuration
在添加所需的依赖项后,我们可以创建我们的 Spring 配置。Spring 配置负责创建 Servlet Filter,该 Servlet Filter 使用由 Spring Session 支持的实现来替换 HttpSession
实现。
After adding the required dependencies, we can create our Spring configuration.
The Spring configuration is responsible for creating a Servlet Filter that replaces the HttpSession
implementation with an implementation backed by Spring Session.
您要做的就是添加以下 Spring 配置:
All you have to do is to add the following Spring Configuration:
Unresolved include directive in modules/ROOT/pages/guides/boot-mongo.adoc - include::example$spring-session-samples/spring-session-sample-boot-mongodb-traditional/src/main/java/org/springframework/session/mongodb/examples/config/HttpSessionConfig.java[]
1 | The @EnableMongoHttpSession annotation creates a Spring Bean with the name of springSessionRepositoryFilter that implements Filter.
This filter is what replaces the default HttpSession with the MongoDB-backed bean. |
2 | Configures the session timeout to 30 minutes. |
Configuring the MongoDB Connection
Spring Boot 自动创建 MongoClient
,它将 Spring Session 连接到本地主机上端口 27017(默认端口)的 MongoDB 服务器。在生产环境中,您需要确保更新您的配置,使其指向您的 MongoDB 服务器。例如,您可在 application.properties 中包含以下项:
Spring Boot automatically creates a MongoClient
that connects Spring Session to a MongoDB Server on localhost on port 27017 (default port).
In a production environment you need to ensure to update your configuration to point to your MongoDB server.
For example, you can include the following in your application.properties
spring.data.mongodb.host=mongo-srv spring.data.mongodb.port=27018 spring.data.mongodb.database=prod
如需了解更多信息,请参阅 Spring Boot 文档的“`HttpSession`到 MongoDB”({docs-url}/spring-boot/docs/current/reference/htmlsingle/#boot-features-connecting-to-mongodb)部分。
For more information, refer to {docs-url}/spring-boot/docs/current/reference/htmlsingle/#boot-features-connecting-to-mongodb[Connecting to MongoDB] portion of the Spring Boot documentation.
Servlet Container Initialization
我们的 Spring Configuration 创建了一个名为 springSessionRepositoryFilter
的 Spring Bean,该 Bean 实现 Filter
。springSessionRepositoryFilter
Bean 负责用由 Spring Session 支持的自定义实现替换 HttpSession
。
Our boot-mongo-configuration created a Spring Bean named springSessionRepositoryFilter
that implements Filter
.
The springSessionRepositoryFilter
bean is responsible for replacing the HttpSession
with a custom implementation that is backed by Spring Session.
为了让我们的 Filter
执行其魔力,Spring 需要加载我们的 Config
类。最后,我们需要确保我们的 Servlet 容器(即 Tomcat)对每个请求使用我们的 springSessionRepositoryFilter
。幸运的是,Spring Boot 为我们处理这两个步骤。
In order for our Filter
to do its magic, Spring needs to load our Config
class.
Last we need to ensure that our Servlet Container (i.e. Tomcat) uses our springSessionRepositoryFilter
for every request.
Fortunately, Spring Boot takes care of both of these steps for us.
MongoDB Sample Application
MongoDB 示例应用程序演示了如何使用 Spring Session 透明利用 MongoDB 来支持使用 Spring Boot 时 Web 应用程序的 HttpSession
。
The MongoDB Sample Application demonstrates how to use Spring Session to transparently leverage MongoDB to back a web application’s HttpSession
when using Spring Boot.
Running the MongoDB Sample Application
您可以获取 源代码 并调用以下命令运行示例:
You can run the sample by obtaining the source code and invoking the following command:
$ ./gradlew :samples:mongo:bootRun
您现在应该能够访问 [role="bare"][role="bare"]http://localhost:8080/ 中的应用程序。
You should now be able to access the application at [role="bare"]http://localhost:8080/
Exploring the security Sample Application
尝试使用该应用程序。输入以下内容以登录:
Try using the application. Enter the following to log in:
-
Username user
-
Password password
现在,单击 Login 按钮。你现在应该看到一条消息,指出你已使用之前输入的用户登录。用户的相关信息存储在 MongoDB 中,而不是 Tomcat 的 HttpSession
实现中。
Now click the Login button.
You should now see a message indicating your are logged in with the user entered previously.
The user’s information is stored in MongoDB rather than Tomcat’s HttpSession
implementation.
How does it work?
我们实际上是将值持久化到 Mongo 中,而不用使用 Tomcat 的 HttpSession
。Spring Session 用支持 Mongo 的实现替换了 HttpSession
。当 Spring Security 的 SecurityContextPersistenceFilter
将 SecurityContext
保存到 HttpSession
中时,它就会持久化到 Mongo 中。
Instead of using Tomcat’s HttpSession
, we are actually persisting the values in Mongo.
Spring Session replaces the HttpSession
with an implementation that is backed by Mongo.
When Spring Security’s SecurityContextPersistenceFilter
saves the SecurityContext
to the HttpSession
it is then persisted into Mongo.
当创建一个新的 HttpSession
时,Spring Session 会在你的浏览器中创建一个名为 SESSION 的 cookie,其中包含你会话的 id。继续,使用 Chrome 或 Firefox 查看 cookie(点击以获得帮助)。
When a new HttpSession
is created, Spring Session creates a cookie named SESSION in your browser that contains the id of your session.
Go ahead and view the cookies (click for help with Chrome or Firefox).
如果你愿意,可以使用 mongo 客户端轻松检查会话。例如,在基于 Linux 的系统上,可以输入:
If you like, you can easily inspect the session using mongo client. For example, on a Linux based system you can type:
示例应用程序使用内嵌式 MongoDB 实例,该实例侦听随机分配的端口。在应用程序启动期间会记录内嵌式 MongoDB 使用的端口,以及连接其的确切命令。 The sample application uses an embedded MongoDB instance that listens on a randomly allocated port. The port used by embedded MongoDB together with exact command to connect to it is logged during application startup. |
$ mongo --port … > use test > db.sessions.find().pretty()
或者,你还可以删除显式密钥。输入以下内容到你的终端,确保用 SESSION Cookie 的值替换 60f17293-839b-477c-bb92-07a9c3658843
:
Alternatively, you can also delete the explicit key. Enter the following into your terminal ensuring to replace 60f17293-839b-477c-bb92-07a9c3658843
with the value of your SESSION cookie:
db.sessions.remove({"_id":"60f17293-839b-477c-bb92-07a9c3658843"})
现在,再次访问 [role="bare"][role="bare"]http://localhost:8080/ 中的应用程序,并观察不再对我们进行身份验证的情况。
Now visit the application at [role="bare"]http://localhost:8080/ and observe that we are no longer authenticated.
Session serialization mechanisms
为了能够在 MongoDB 中保存会话对象,我们需要提供序列化/反序列化机制。
To be able to persist session objects in MongoDB we need to provide the serialization/deserialization mechanism.
默认情况下,Spring Session MongoDB 将使用 JdkMongoSessionConverter
。
By default, Spring Session MongoDB will use JdkMongoSessionConverter
.
然而,你可以通过简单的将以下代码添加到你的 Boot 应用来切换到 JacksonMongoSessionConverter
:
However, you may switch to JacksonMongoSessionConverter
by merely adding the following code to your Boot app:
@Bean
JacksonMongoSessionConverter mongoSessionConverter() {
return new JacksonMongoSessionConverter();
}
JacksonMongoSessionConverter
此机制使用 Jackson 将会话对象序列化为/从 JSON。
This mechanism uses Jackson to serialize session objects to/from JSON.
通过创建以下 bean:
By creating the following bean:
@Bean
JacksonMongoSessionConverter mongoSessionConverter() {
return new JacksonMongoSessionConverter();
}
…您能够从默认的(基于 JDK 的序列化)切换到使用 Jackson。
…you are able to switch from the default (JDK-based serialization) to using Jackson.
如果您要与 Spring Security 集成(通过在 MongoDB 中存储会话),该配置将注册合适的白名单组件,以便 Spring Security 正常工作。
If you are integrating with Spring Security (by storing your sessions in MongoDB), this configuration will register the proper whitelisted components so Spring Security works properly.
如果您想提供自定义 Jackson 模块,您可以通过明确注册模块来执行此操作,如下所示:
If you would like to provide custom Jackson modules you can do it by explicitly registering modules as shown below:
Unresolved include directive in modules/ROOT/pages/http-session.adoc - include::example$spring-session-data-mongodb-dir/src/integration-test/java/org/springframework/session/data/mongo/integration/MongoRepositoryJacksonITest.java[]
JdkMongoSessionConverter
JdkMongoSessionConverter
使用标准的 Java 序列化以二进制形式将会话属性映射持久性存储在 MongoDB 中。然而,诸如 id、访问时间等标准会话元素仍作为普通的 Mongo 对象进行写入,并且可以在不需要额外工作的情况下进行读取和查询。如果未定义显式的 AbstractMongoSessionConverter
Bean,将使用 JdkMongoSessionConverter
。
JdkMongoSessionConverter
uses standard Java serialization to persist session attributes map to MongoDB in a binary form.
However, standard session elements like id, access time, etc are still written as a plain Mongo objects and can be read and queried without additional effort.
JdkMongoSessionConverter
is used if no explicit AbstractMongoSessionConverter
Bean has been defined.
还存在一个使用 Serializer
和 Deserializer
对象的构造函数,它允许你传递自定义实现,这在想要使用非默认类加载器时尤为重要。
There is also a constructor taking Serializer
and Deserializer
objects, allowing you to pass custom implementations, which is especially important when you want to use non-default classloader.
HttpSession
with JDBC
你可以通过在使用 `HttpSession`的任何内容之前添加一个 Servlet 过滤器来使用 `HttpSession`的 Spring Session。你可以使用以下任何一种方式:
You can use Spring Session with HttpSession
by adding a servlet filter before anything that uses the HttpSession
.
You can choose to do in any of the following ways:
JDBC Java-based Configuration
本部分介绍了在使用基于 Java 的配置时如何使用关系数据库来支持 HttpSession
。
This section describes how to use a relational database to back HttpSession
when you use Java-based configuration.
HttpSession JDBC Sample 提供了一个关于如何通过 Java 配置整合 Spring Session 和 |
The HttpSession JDBC Sample provides a working sample of how to integrate Spring Session and |
@14
Spring Session - HttpSession (Quick Start)
Rob Winch, Vedran Pavić
此指南将介绍如何使用 Spring Session 透明地利用关系数据库来使用 Java 配置来为 Web 应用程序的 HttpSession
提供支持。
This guide describes how to use Spring Session to transparently leverage a relational database to back a web application’s HttpSession
with Java Configuration.
您可以在httpsession-jdbc sample application中找到已完成指南。 |
You can find the completed guide in the httpsession-jdbc-sample. |
Updating Dependencies
在使用 Spring 会话之前,您必须更新依赖。如果您使用 Maven,您必须添加以下依赖:
Before you use Spring Session, you must update your dependencies. If you use Maven, you must add the following dependencies:
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
<version>{spring-session-version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>{spring-core-version}</version>
</dependency>
</dependencies>
Spring Java Configuration
添加所需的依赖项后,我们就可以创建我们的 Spring 配置。Spring 配置负责创建一个 Servlet 过滤器,它将 HttpSession
实现替换为由 Spring Session 支持的实现。为此,请添加以下 Spring 配置:
After adding the required dependencies, we can create our Spring configuration.
The Spring configuration is responsible for creating a Servlet Filter that replaces the HttpSession
implementation with an implementation backed by Spring Session.
To do so, add the following Spring Configuration:
Unresolved include directive in modules/ROOT/pages/guides/java-jdbc.adoc - include::example$spring-session-samples/spring-session-sample-javaconfig-jdbc/src/main/java/sample/Config.java[]
1 | The @EnableJdbcHttpSession annotation creates a Spring Bean with the name of springSessionRepositoryFilter .
That bean implements Filter .
The filter is in charge of replacing the HttpSession implementation to be backed by Spring Session.
In this instance, Spring Session is backed by a relational database. |
2 | We create a dataSource that connects Spring Session to an embedded instance of an H2 database.
We configure the H2 database to create database tables by using the SQL script that is included in Spring Session. |
3 | We create a transactionManager that manages transactions for previously configured dataSource . |
有关如何配置数据访问相关问题的其他信息,请参阅 {docs-url}/spring/docs/{spring-core-version}/reference/html/data-access.html[Spring Framework Reference Documentation]。
For additional information on how to configure data access related concerns, see the {docs-url}/spring/docs/{spring-core-version}/reference/html/data-access.html[Spring Framework Reference Documentation].
Java Servlet Container Initialization
我们的 Spring Configuration 创建了一个名为 springSessionRepositoryFilter
的 Spring Bean,该 Bean 实施了 Filter
。springSessionRepositoryFilter
Bean 负责使用由 Spring Session 支持的自定义实现来替换 HttpSession
。
Our httpsession-jdbc-spring-configuration created a Spring bean named springSessionRepositoryFilter
that implements Filter
.
The springSessionRepositoryFilter
bean is responsible for replacing the HttpSession
with a custom implementation that is backed by Spring Session.
为了让我们的 Filter
发挥其魔力,Spring 需要加载我们的 Config
类。最后,我们需要确保我们的 Servlet 容器(即 Tomcat)针对每个请求使用我们的 springSessionRepositoryFilter
。幸运的是,Spring Session 提供了一个名为 AbstractHttpSessionApplicationInitializer
的实用程序类,可以轻松地完成这两步。以下示例显示了如何执行此操作:
In order for our Filter
to do its magic, Spring needs to load our Config
class.
Last, we need to ensure that our Servlet Container (that is, Tomcat) uses our springSessionRepositoryFilter
for every request.
Fortunately, Spring Session provides a utility class named AbstractHttpSessionApplicationInitializer
to make both of these steps easy.
The following example shows how to do so:
Unresolved include directive in modules/ROOT/pages/guides/java-jdbc.adoc - include::example$spring-session-samples/spring-session-sample-javaconfig-jdbc/src/main/java/sample/Initializer.java[]
我们的类(Initializer)的名称无关紧要。重要的是我们扩展 AbstractHttpSessionApplicationInitializer
。
The name of our class (Initializer) does not matter.
What is important is that we extend AbstractHttpSessionApplicationInitializer
.
1 | The first step is to extend AbstractHttpSessionApplicationInitializer .
Doing so ensures that the Spring bean named springSessionRepositoryFilter is registered with our Servlet Container for every request. |
2 | AbstractHttpSessionApplicationInitializer also provides a mechanism to ensure Spring loads our Config . |
Multiple DataSources
Spring Session 提供了 @SpringSessionDataSource
限定符,它允许你在 JdbcIndexedSessionRepository
中明确声明应该注入哪个 DataSource
bean。这在应用程序上下文中存在多个 DataSource
bean 的情况下特别有用。
Spring Session provides the @SpringSessionDataSource
qualifier, allowing you to explicitly declare which DataSource
bean should be injected in JdbcIndexedSessionRepository
.
This is particularly useful in scenarios with multiple DataSource
beans present in the application context.
以下示例演示了如何执行此操作:
The following example shows how to do so:
@EnableJdbcHttpSession
public class Config {
@Bean
@SpringSessionDataSource (1)
public EmbeddedDatabase firstDataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2).addScript("org/springframework/session/jdbc/schema-h2.sql").build();
}
@Bean
public HikariDataSource secondDataSource() {
// ...
}
}
1 | This qualifier declares that firstDataSource is to be used by Spring Session. |
httpsession-jdbc
Sample Application
本节介绍如何处理 httpsession-jdbc
Sample Application。
This section describes how to work with the httpsession-jdbc
Sample Application.
Running the httpsession-jdbc
Sample Application
您可以获取 源代码 并调用以下命令运行示例:
You can run the sample by obtaining the source code and invoking the following command:
$ ./gradlew :spring-session-sample-javaconfig-jdbc:tomcatRun
您现在应该能够访问 [role="bare"][role="bare"]http://localhost:8080/ 中的应用程序。
You should now be able to access the application at [role="bare"]http://localhost:8080/
Exploring the httpsession-jdbc
Sample Application
现在你可以尝试使用此应用程序。为此,请填写以下信息的表单:
Now you can try using the application. To do so, fill out the form with the following information:
-
Attribute Name: username
-
Attribute Value: rob
然后,请点击 Set Attribute 按钮。您现在应该可以看到表中显示的值了。
Now click the Set Attribute button. You should now see the values displayed in the table.
How Does It Work?
我们与 HttpSession
中显示的标准 SessionServlet
进行交互,这在下表中有所说明:
We interact with the standard HttpSession
in the SessionServlet
shown in the following listing:
Unresolved include directive in modules/ROOT/pages/guides/java-jdbc.adoc - include::example$spring-session-samples/spring-session-sample-javaconfig-jdbc/src/main/java/sample/SessionServlet.java[]
不使用 Tomcat 的 HttpSession
,我们在 H2 数据库中永久保存这些值。Spring Session 会在你的浏览器中创建一个名为 SESSION
的 cookie。该 cookie 包含你会话的 ID。你可以使用 Chrome 或 Firefox 查看 cookie。
Instead of using Tomcat’s HttpSession
, we persist the values in H2 database.
Spring Session creates a cookie named SESSION
in your browser.
That cookie contains the ID of your session.
You can view the cookies (with Chrome or Firefox).
如果你想的话,可以使用位于 [role="bare"][role="bare"]http://localhost:8080/h2-console/ 的 H2 web 控制台来移除会话(为 JDBC URL 使用 jdbc:h2:mem:testdb
)。
If you like, you can remove the session by using the H2 web console available at: [role="bare"]http://localhost:8080/h2-console/ (use jdbc:h2:mem:testdb
for JDBC URL).
现在,您可以访问 [role="bare"][role="bare"]http://localhost:8080/ 中的应用程序并看到我们添加的属性不再显示。
Now you can visit the application at [role="bare"]http://localhost:8080/ and see that the attribute we added is no longer displayed.
JDBC XML-based Configuration
本节介绍了在基于 XML 的配置中使用关系数据库作为 HttpSession
的方法。
This section describes how to use a relational database to back HttpSession
when you use XML based configuration.
HttpSession JDBC XML Sample 提供了一个关于如何通过 XML 配置整合 Spring Session 和 |
The HttpSession JDBC XML Sample provides a working sample of how to integrate Spring Session and |
@15
Spring Session - HttpSession (Quick Start)
Rob Winch, Vedran Pavić
此指南介绍如何使用 Spring Session 透明地利用关系数据库作为基于 XML 的配置 Web 应用程序的 HttpSession
。
This guide describes how to use Spring Session to transparently leverage a relational to back a web application’s HttpSession
with XML based configuration.
您可以在httpsession-jdbc-xml sample application中找到已完成指南。 |
You can find the completed guide in the httpsession-jdbc-xml-sample. |
Updating Dependencies
在你使用 Spring Session 之前,你必须更新你的依赖项。如果你使用的是 Maven,你必须添加以下依赖项:
Before you use Spring Session, you must update your dependencies. If you are using Maven, you must add the following dependencies:
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
<version>{spring-session-version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>{spring-core-version}</version>
</dependency>
</dependencies>
Spring XML Configuration
在添加必需的依赖项后,我们可以创建 Spring 配置。Spring 配置负责创建一个 servlet 筛选器,它使用 Spring Session 支持的实现替换 HttpSession
实现。以下清单展示了如何添加以下 Spring 配置:
After adding the required dependencies, we can create our Spring configuration.
The Spring configuration is responsible for creating a servlet filter that replaces the HttpSession
implementation with an implementation backed by Spring Session.
The following listing shows how to add the following Spring Configuration:
Unresolved include directive in modules/ROOT/pages/guides/xml-jdbc.adoc - include::example$spring-session-samples/spring-session-sample-xml-jdbc/src/main/webapp/WEB-INF/spring/session.xml[]
1 | We use the combination of <context:annotation-config/> and JdbcHttpSessionConfiguration because Spring Session does not yet provide XML Namespace support (see gh-104).
This creates a Spring bean with the name of springSessionRepositoryFilter .
That bean implements Filter .
The filter is in charge of replacing the HttpSession implementation to be backed by Spring Session.
In this instance, Spring Session is backed by a relational database. |
2 | We create a dataSource that connects Spring Session to an embedded instance of an H2 database.
We configure the H2 database to create database tables by using the SQL script that is included in Spring Session. |
3 | We create a transactionManager that manages transactions for previously configured dataSource . |
有关如何配置数据访问相关问题的其他信息,请参阅 {docs-url}/spring/docs/{spring-core-version}/spring-framework-reference/data-access.html[Spring Framework Reference Documentation]。
For additional information on how to configure data access-related concerns, see the {docs-url}/spring/docs/{spring-core-version}/spring-framework-reference/data-access.html[Spring Framework Reference Documentation].
XML Servlet Container Initialization
我们的 Spring Configuration 创建了一个名为 springSessionRepositoryFilter
的 Spring bean,它实现了 Filter
。springSessionRepositoryFilter
bean 负责使用 Spring Session 支持的自定义实现替换 HttpSession
。
Our httpsession-jdbc-xml-spring-configuration created a Spring bean named springSessionRepositoryFilter
that implements Filter
.
The springSessionRepositoryFilter
bean is responsible for replacing the HttpSession
with a custom implementation that is backed by Spring Session.
为了让 Filter
发挥其作用,我们需要指示 Spring 加载我们的 session.xml
配置。我们使用以下配置执行此操作:
In order for our Filter
to do its magic, we need to instruct Spring to load our session.xml
configuration.
We do so with the following configuration:
Unresolved include directive in modules/ROOT/pages/guides/xml-jdbc.adoc - include::example$spring-session-samples/spring-session-sample-xml-jdbc/src/main/webapp/WEB-INF/web.xml[]
Unresolved include directive in modules/ROOT/pages/guides/xml-jdbc.adoc - include::example$spring-session-samples/spring-session-sample-xml-jdbc/src/main/webapp/WEB-INF/web.xml[]
{docs-url}/spring/docs/{spring-core-version}/spring-framework-reference/core.html#context-create[ContextLoaderListener
] 读入 contextConfigLocation
,并拾取到我们的 session.xml 配置。
The {docs-url}/spring/docs/{spring-core-version}/spring-framework-reference/core.html#context-create[ContextLoaderListener
] reads the contextConfigLocation
and picks up our session.xml configuration.
最后,我们需要确保我们的 Servlet 容器(即 Tomcat)针对每个请求使用我们的 springSessionRepositoryFilter
。以下代码段为我们执行最后一步:
Last, we need to ensure that our Servlet Container (that is, Tomcat) uses our springSessionRepositoryFilter
for every request.
The following snippet performs this last step for us:
Unresolved include directive in modules/ROOT/pages/guides/xml-jdbc.adoc - include::example$spring-session-samples/spring-session-sample-xml-jdbc/src/main/webapp/WEB-INF/web.xml[]
{docs-url}/spring-framework/docs/{spring-core-version}/javadoc-api/org/springframework/web/filter/DelegatingFilterProxy.html[DelegatingFilterProxy
] 按名称查找一个 Bean springSessionRepositoryFilter
,并将其转换为 Filter
。对于调用 DelegatingFilterProxy`的每个请求,都调用 `springSessionRepositoryFilter
。
The {docs-url}/spring-framework/docs/{spring-core-version}/javadoc-api/org/springframework/web/filter/DelegatingFilterProxy.html[DelegatingFilterProxy
] looks up a bean named springSessionRepositoryFilter
and casts it to a Filter
.
For every request on which DelegatingFilterProxy
is invoked, the springSessionRepositoryFilter
is invoked.
httpsession-jdbc-xml
Sample Application
本节描述了如何使用 httpsession-jdbc-xml
示例应用程序。
This section describes how to work with the httpsession-jdbc-xml
Sample Application.
Running the httpsession-jdbc-xml
Sample Application
您可以获取 源代码 并调用以下命令运行示例:
You can run the sample by obtaining the source code and invoking the following command:
$ ./gradlew :spring-session-sample-xml-jdbc:tomcatRun
您现在应该能够访问 [role="bare"][role="bare"]http://localhost:8080/ 中的应用程序。
You should now be able to access the application at [role="bare"]http://localhost:8080/
Exploring the httpsession-jdbc-xml
Sample Application
现在你可以尝试使用此应用程序。为此,请填写以下信息的表单:
Now you can try using the application. To do so, fill out the form with the following information:
-
Attribute Name: username
-
Attribute Value: rob
然后,请点击 Set Attribute 按钮。您现在应该可以看到表中显示的值了。
Now click the Set Attribute button. You should now see the values displayed in the table.
How Does It Work?
我们在以下 SessionServlet
中与标准 HttpSession
进行交互:
We interact with the standard HttpSession
in the following SessionServlet
:
Unresolved include directive in modules/ROOT/pages/guides/xml-jdbc.adoc - include::example$spring-session-samples/spring-session-sample-xml-jdbc/src/main/java/sample/SessionServlet.java[]
不使用 Tomcat 的 HttpSession
,我们在 H2 数据库中永久保存这些值。Spring Session 会在你的浏览器中创建一个名为 SESSION
的 cookie。该 cookie 包含你会话的 ID。你可以使用 Chrome 或 Firefox 查看 cookie。
Instead of using Tomcat’s HttpSession
, we persist the values in the H2 database.
Spring Session creates a cookie named SESSION
in your browser. That cookie contains the ID of your session.
You can view the cookies (with Chrome or Firefox).
你可以使用位于 [role="bare"][role="bare"]http://localhost:8080/h2-console/ 的 H2 web 控制台来移除会话(为 JDBC URL 使用 jdbc:h2:mem:testdb
)。
You can remove the session by using H2 web console available at: [role="bare"]http://localhost:8080/h2-console/ (use jdbc:h2:mem:testdb
for JDBC URL)
现在你可以访问位于 [role="bare"][role="bare"]http://localhost:8080/ 的应用,并观察我们添加的属性不再显示。
Now you can visit the application at [role="bare"]http://localhost:8080/ and observe that the attribute we added is no longer displayed.
JDBC Spring Boot-based Configuration
本节介绍了在使用 Spring Boot 时如何使用关系数据库作为 HttpSession
的后盾。
This section describes how to use a relational database to back HttpSession
when you use Spring Boot.
HttpSession JDBC Spring Boot Sample 提供了一个关于如何通过 Spring Boot 整合 Spring Session 和 |
The HttpSession JDBC Spring Boot Sample provides a working sample of how to integrate Spring Session and |
@16
Spring Session - Spring Boot
Rob Winch, Vedran Pavić
本指南介绍了在使用 Spring Boot 时如何使用 Spring Session 透明利用关系数据库来支持 Web 应用程序的 HttpSession
。
This guide describes how to use Spring Session to transparently leverage a relational database to back a web application’s HttpSession
when you use Spring Boot.
您可以在httpsession-jdbc-boot sample application中找到已完成指南。 |
You can find the completed guide in the httpsession-jdbc-boot-sample. |
Updating Dependencies
在使用 Spring Session 之前,必须更新你的依赖项。我们假设你正在与正在运行的 Spring Boot Web 应用程序一起使用。如果你使用 Maven,则必须添加以下依赖项:
Before you use Spring Session, you must update your dependencies. We assume you are working with a working Spring Boot web application. If you use Maven, you must add the following dependencies:
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
</dependency>
</dependencies>
Spring Boot 为 Spring Session 模块提供了依赖管理,因此你无需明确声明依赖项版本。
Spring Boot provides dependency management for Spring Session modules, so you need not explicitly declare the dependency version.
Spring Boot Configuration
在添加必需的依赖项后,我们可以创建 Spring Boot 配置。由于一流的自动配置支持,只需添加依赖项,Spring Boot 就为我们设置了关系数据库支持的 Spring Session。
After adding the required dependencies, we can create our Spring Boot configuration. Thanks to first-class auto-configuration support, just by adding the dependency Spring Boot will set up Spring Session backed by a relational database for us.
如果 classpath 上存在单个 Spring Session 模块,Spring Boot 会自动使用该存储实现。如果你有多个实现,你必须选择要用于存储会话的 StoreType,如上所示。
If a single Spring Session module is present on the classpath, Spring Boot uses that store implementation automatically. If you have more than one implementation, you must choose the StoreType that you wish to use to store the sessions, as shows above.
在表面之下,Spring Boot 应用的配置等同于手动添加 @EnableJdbcHttpSession
注解。这创建了一个名为 springSessionRepositoryFilter
的 Spring bean。该 bean 实现了 Filter
。该筛选器负责替换 HttpSession
实现,以便由 Spring Session 支持。
Under the hood, Spring Boot applies configuration that is equivalent to manually adding the @EnableJdbcHttpSession
annotation.
This creates a Spring bean with the name of springSessionRepositoryFilter
. That bean implements Filter
.
The filter is in charge of replacing the HttpSession
implementation to be backed by Spring Session.
你可以使用 application.properties
进一步自定义。以下清单显示了如何执行此操作:
You can further customize by using application.properties
.
The following listing shows how to do so:
server.servlet.session.timeout= # Session timeout. If a duration suffix is not specified, seconds are used. spring.session.jdbc.initialize-schema=embedded # Database schema initialization mode. spring.session.jdbc.schema=classpath:org/springframework/session/jdbc/schema-@@platform@@.sql # Path to the SQL file to use to initialize the database schema. spring.session.jdbc.table-name=SPRING_SESSION # Name of the database table used to store sessions.
有关更多信息,请参阅 Spring Boot 文档中的 {docs-url}/spring-boot/docs/{spring-boot-version}/reference/htmlsingle/#boot-features-session[Spring Session] 部分。
For more information, see the {docs-url}/spring-boot/docs/{spring-boot-version}/reference/htmlsingle/#boot-features-session[Spring Session] portion of the Spring Boot documentation.
Configuring the DataSource
Spring Boot 自动创建 DataSource
,它将 Spring Session 连接到 H2 数据库的嵌入式实例。在生产环境中,你需要更新配置以指向你的关系数据库。例如,你可以在 application.properties 中包含以下内容:
Spring Boot automatically creates a DataSource
that connects Spring Session to an embedded instance of an H2 database.
In a production environment, you need to update your configuration to point to your relational database.
For example, you can include the following in your application.properties:
spring.datasource.url= # JDBC URL of the database. spring.datasource.username= # Login username of the database. spring.datasource.password= # Login password of the database.
有关更多信息,请参阅 Spring Boot 文档的 {docs-url}/spring-boot/docs/{spring-boot-version}/reference/htmlsingle/#boot-features-configure-datasource[配置数据源] 部分。
For more information, see the {docs-url}/spring-boot/docs/{spring-boot-version}/reference/htmlsingle/#boot-features-configure-datasource[Configure a DataSource] portion of the Spring Boot documentation.
Servlet Container Initialization
我们的 Spring Boot Configuration 创建了一个名为 springSessionRepositoryFilter
的 Spring bean,它实现了 Filter
。springSessionRepositoryFilter
bean 负责使用 Spring Session 支持的自定义实现替换 HttpSession
。
Our httpsession-jdbc-boot-spring-configuration created a Spring bean named springSessionRepositoryFilter
that implements Filter
.
The springSessionRepositoryFilter
bean is responsible for replacing the HttpSession
with a custom implementation that is backed by Spring Session.
为了让我们的 Filter
发挥作用,Spring 需要加载我们的 Config
类。最后,我们需要确保我们的 Servlet 容器(即 Tomcat)在每个请求中使用我们的 springSessionRepositoryFilter
。幸运的是,Spring Boot 替我们执行这两个步骤。
In order for our Filter
to do its magic, Spring needs to load our Config
class.
Last, we need to ensure that our Servlet Container (that is, Tomcat) uses our springSessionRepositoryFilter
for every request.
Fortunately, Spring Boot takes care of both of these steps for us.
httpsession-jdbc-boot
Sample Application
httpsession-jdbc-boot 示例应用程序演示了在使用 Spring Boot 时如何使用 Spring Session 透明利用 H2 数据库来支持 Web 应用程序的 HttpSession
。
The httpsession-jdbc-boot Sample Application demonstrates how to use Spring Session to transparently leverage an H2 database to back a web application’s HttpSession
when you use Spring Boot.
Running the httpsession-jdbc-boot
Sample Application
您可以获取 源代码 并调用以下命令运行示例:
You can run the sample by obtaining the source code and invoking the following command:
$ ./gradlew :spring-session-sample-boot-jdbc:bootRun
您现在应该能够访问 [role="bare"][role="bare"]http://localhost:8080/ 中的应用程序。
You should now be able to access the application at [role="bare"]http://localhost:8080/
Exploring the Security Sample Application
您现在可以尝试使用该应用程序。为此,请输入以下内容进行登录:
You can now try using the application. To do so, enter the following to log in:
-
Username user
-
Password password
现在,单击 Login 按钮。你现在应该看到一条消息,指出你已使用之前输入的用户登录。用户的相关信息存储在 H2 数据库中,而不是 Tomcat 的 HttpSession
实现中。
Now click the Login button.
You should now see a message indicating that your are logged in with the user entered previously.
The user’s information is stored in the H2 database rather than Tomcat’s HttpSession
implementation.
How Does It Work?
我们持久化值到 H2 数据库中,而不是使用 Tomcat 的 HttpSession
。Spring Session 用一个关系数据库支持的实现替换了 HttpSession
。当 Spring Security 的 SecurityContextPersistenceFilter
将 SecurityContext
保存到 HttpSession
中时,它就会持久化到 H2 数据库中。
Instead of using Tomcat’s HttpSession
, we persist the values in the H2 database.
Spring Session replaces the HttpSession
with an implementation that is backed by a relational database.
When Spring Security’s SecurityContextPersistenceFilter
saves the SecurityContext
to the HttpSession
, it is then persisted into the H2 database.
当创建新的 HttpSession
时,Spring Session 在浏览器中创建一个名为 SESSION
的 cookie。该 cookie 包含会话 ID。您可以查看 cookie(使用 Chrome 或 Firefox)。
When a new HttpSession
is created, Spring Session creates a cookie named SESSION
in your browser. That cookie contains the ID of your session.
You can view the cookies (with Chrome or Firefox).
你可以使用位于 [role="bare"][role="bare"]http://localhost:8080/h2-console/ 的 H2 web 控制台来移除会话(为 JDBC URL 使用 jdbc:h2:mem:testdb
)。
You can remove the session by using the H2 web console available at: [role="bare"]http://localhost:8080/h2-console/ (use jdbc:h2:mem:testdb
for JDBC URL).
现在,您可以访问 [role="bare"][role="bare"]http://localhost:8080/ 中的应用程序并看到我们不再通过身份验证。
Now you can visit the application at [role="bare"]http://localhost:8080/ and see that we are no longer authenticated.
HttpSession with Hazelcast
使用 `HttpSession`的 Spring Session 可通过在使用 `HttpSession`的任何内容之前添加一个 Servlet 过滤器来启用。
Using Spring Session with HttpSession
is enabled by adding a Servlet Filter before anything that uses the HttpSession
.
本节介绍了如何使用基于 Java 的配置,使用 Hazelcast 来支持 HttpSession
。
This section describes how to use Hazelcast to back HttpSession
by using Java-based configuration.
Hazelcast Spring Sample 提供了一个工作示例,演示如何通过使用 Java 配置整合 Spring Session 和 |
The Hazelcast Spring Sample provides a working sample of how to integrate Spring Session and |
@17
Spring Session and Spring Security with Hazelcast
Tommy Ludwig; Rob Winch
本指南描述了使用 Hazelcast 作为数据存储时,如何将 Spring 会话与 Spring 安全性配合使用。假设您已向应用程序应用了 Spring 安全性。
This guide describes how to use Spring Session along with Spring Security when you use Hazelcast as your data store. It assumes that you have already applied Spring Security to your application.
你可以在Hazelcast Spring Security sample application中找到已完成的指南。 |
You cand find the completed guide in the hazelcast-spring-security-sample. |
Updating Dependencies
在使用 Spring 会话之前,您必须更新依赖。如果您使用 Maven,您必须添加以下依赖:
Before you use Spring Session, you must update your dependencies. If you use Maven, you must add the following dependencies:
<dependencies>
<!-- ... -->
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast</artifactId>
<version>{hazelcast-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 配置:
After adding the required dependencies, we can create our Spring configuration.
The Spring configuration is responsible for creating a servlet filter that replaces the HttpSession
implementation with an implementation backed by Spring Session.
To do so, add the following Spring Configuration:
/*
* Copyright 2014-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package docs.http;
import com.hazelcast.config.AttributeConfig;
import com.hazelcast.config.Config;
import com.hazelcast.config.IndexConfig;
import com.hazelcast.config.IndexType;
import com.hazelcast.config.SerializerConfig;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.MapSession;
import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository;
import org.springframework.session.hazelcast.HazelcastSessionSerializer;
import org.springframework.session.hazelcast.PrincipalNameExtractor;
import org.springframework.session.hazelcast.config.annotation.web.http.EnableHazelcastHttpSession;
// tag::config[]
@EnableHazelcastHttpSession (1)
@Configuration
public class HazelcastHttpSessionConfig {
@Bean
public HazelcastInstance hazelcastInstance() {
Config config = new Config();
AttributeConfig attributeConfig = new AttributeConfig()
.setName(HazelcastIndexedSessionRepository.PRINCIPAL_NAME_ATTRIBUTE)
.setExtractorClassName(PrincipalNameExtractor.class.getName());
config.getMapConfig(HazelcastIndexedSessionRepository.DEFAULT_SESSION_MAP_NAME) (2)
.addAttributeConfig(attributeConfig)
.addIndexConfig(
new IndexConfig(IndexType.HASH, HazelcastIndexedSessionRepository.PRINCIPAL_NAME_ATTRIBUTE));
SerializerConfig serializerConfig = new SerializerConfig();
serializerConfig.setImplementation(new HazelcastSessionSerializer()).setTypeClass(MapSession.class);
config.getSerializationConfig().addSerializerConfig(serializerConfig); (3)
return Hazelcast.newHazelcastInstance(config); (4)
}
}
// end::config[]
1 | The @EnableHazelcastHttpSession annotation creates a Spring bean named springSessionRepositoryFilter that implements Filter .
The filter is in charge of replacing the HttpSession implementation to be backed by Spring Session.
In this instance, Spring Session is backed by Hazelcast. |
2 | In order to support retrieval of sessions by principal name index, an appropriate ValueExtractor needs to be registered.
Spring Session provides PrincipalNameExtractor for this purpose. |
3 | In order to serialize MapSession objects efficiently, HazelcastSessionSerializer needs to be registered. If this
is not set, Hazelcast will serialize sessions using native Java serialization. |
4 | We create a HazelcastInstance that connects Spring Session to Hazelcast.
By default, the application starts and connects to an embedded instance of Hazelcast.
For more information on configuring Hazelcast, see the reference documentation. |
如果选择`HazelcastSessionSerializer`,则必须在所有 Hazelcast 集群成员开始之前对所有 Hazelcast 集群成员进行配置。在 Hazelcast 集群中,所有成员都应使用用于会话的相同序列化方法。此外,如果使用 Hazelcast 客户端/服务器拓扑结构,则成员和客户端都必须使用相同序列化方法。可以使用`ClientConfig`注册序列化程序并使用与成员相同的`SerializerConfiguration`。 |
If |
Servlet Container Initialization
我们的 Spring Configuration 创建了一个名为 springSessionRepositoryFilter
的 Spring bean,它实现 Filter
。 springSessionRepositoryFilter
bean 负责用由 Spring Session 支持的自定义实现替换 HttpSession
。
Our Spring Configuration created a Spring bean named springSessionRepositoryFilter
that implements Filter
.
The springSessionRepositoryFilter
bean is responsible for replacing the HttpSession
with a custom implementation that is backed by Spring Session.
为了让我们的 Filter`发挥作用,Spring 需要加载我们的 `SessionConfig
类。由于我们的应用程序已经通过使用我们的 SecurityInitializer
类加载了 Spring 配置,我们可以将我们的 SessionConfig
添加到该类。以下清单显示了如何执行此操作:
In order for our Filter
to do its magic, Spring needs to load our SessionConfig
class.
Since our application is already loading Spring configuration by using our SecurityInitializer
class, we can add our SessionConfig
class to it.
The following listing shows how to do so:
Unresolved include directive in modules/ROOT/pages/guides/java-hazelcast.adoc - include::example$spring-session-samples/spring-session-sample-javaconfig-hazelcast/src/main/java/sample/SecurityInitializer.java[]
最后,我们需要确保我们的 Servlet 容器(即 Tomcat)对每个请求使用我们的 springSessionRepositoryFilter
。Spring 会话的 springSessionRepositoryFilter
在 Spring Security 的 springSecurityFilterChain
之前调用非常重要。这样做可以确保 Spring Security 使用的 HttpSession
由 Spring 会话支持。幸运的是,Spring 会话提供了一个名为 AbstractHttpSessionApplicationInitializer
的实用程序类,使此操作变得简单。以下示例显示了如何执行此操作:
Last, we need to ensure that our Servlet Container (that is, Tomcat) uses our springSessionRepositoryFilter
for every request.
It is extremely important that Spring Session’s springSessionRepositoryFilter
is invoked before Spring Security’s springSecurityFilterChain
.
Doing so ensures that the HttpSession
that Spring Security uses is backed by Spring Session.
Fortunately, Spring Session provides a utility class named AbstractHttpSessionApplicationInitializer
that makes this doing so easy.
The following example shows how to do so:
Unresolved include directive in modules/ROOT/pages/guides/java-hazelcast.adoc - include::example$spring-session-samples/spring-session-sample-javaconfig-hazelcast/src/main/java/sample/Initializer.java[]
我们的类 ( |
The name of our class ( |
通过扩展 AbstractHttpSessionApplicationInitializer
,我们确保为 Spring 安全的 springSecurityFilterChain
注册名为 springSessionRepositoryFilter
的 Spring Bean 以便在对每个请求进行之前。
By extending AbstractHttpSessionApplicationInitializer
, we ensure that the Spring Bean named springSessionRepositoryFilter
is registered with our servlet container for every request before Spring Security’s springSecurityFilterChain
.
Hazelcast Spring Security Sample Application
本节描述如何使用 Hazelcast Spring 安全性示例应用程序。
This section describes how to work with the Hazelcast Spring Security sample application.
Running the Sample Application
您可以获取 源代码 并调用以下命令运行示例:
You can run the sample by obtaining the source code and invoking the following command:
$ ./gradlew :spring-session-sample-javaconfig-hazelcast:tomcatRun
默认情况下,Hazelcast 以嵌入模式在你的应用程序中运行。但是,如果你希望连接到独立实例,则可以通过按照 reference documentation 中的说明进行配置。 |
By default, Hazelcast runs in embedded mode with your application. However, if you want to connect to a standalone instance instead, you can configure it by following the instructions in the reference documentation. |
您现在应该能够访问 [role="bare"][role="bare"]http://localhost:8080/ 中的应用程序。
You should now be able to access the application at [role="bare"]http://localhost:8080/
Exploring the Security Sample Application
您现在可以尝试使用该应用程序。为此,请输入以下内容进行登录:
You can now try using the application. To do so, enter the following to log in:
-
Username user
-
Password password
单击 Login 按钮。您现在应该看到一条消息,指示您已使用之前输入的用户登录。用户的信息存储在 Hazelcast 中,而不是 Tomcat HttpSession
实现中。
Now click the Login button.
You should now see a message indicating that your are logged in with the user entered previously.
The user’s information is stored in Hazelcast rather than Tomcat’s HttpSession
implementation.
How Does It Work?
我们不会使用 Tomcat 的 HttpSession
,而是将这些值持久保存到 Hazelcast 中。Spring 会话将 HttpSession
替换为由 Hazelcast 中的 Map
支持的实现。当 Spring 安全性的 SecurityContextPersistenceFilter
将 SecurityContext
保存到 HttpSession
时,它就被持久保存到 Hazelcast 中。
Instead of using Tomcat’s HttpSession
, we persist the values in Hazelcast.
Spring Session replaces the HttpSession
with an implementation that is backed by a Map
in Hazelcast.
When Spring Security’s SecurityContextPersistenceFilter
saves the SecurityContext
to the HttpSession
, it is then persisted into Hazelcast.
Interacting with the Data Store
您可以使用 a Java client one of the other clients 或 management center 来移除会话。
You can remove the session by using a Java client, one of the other clients, or the management center.
Using the Console
例如,要连接到 Hazelcast 节点后使用管理中心控制台删除会话,请运行以下命令:
For example, to remove the session by using the management center console after connecting to your Hazelcast node, run the following commands:
default> ns spring:session:sessions spring:session:sessions> m.clear
Hazelcast 文档包含有关 the console 的说明。 |
The Hazelcast documentation has instructions for the console. |
或者,您也可以删除显式密钥。在控制台输入以下内容,务必将 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
替换为 SESSION
cookie 的值:
Alternatively, you can also delete the explicit key. Enter the following into the console, being sure to replace 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
with the value of your SESSION
cookie:
spring:session:sessions> m.remove 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
现在,再次访问 [role="bare"][role="bare"]http://localhost:8080/ 中的应用程序,并观察不再对我们进行身份验证的情况。
Now visit the application at [role="bare"]http://localhost:8080/ and observe that we are no longer authenticated.
Using the REST API
如文档中介绍其他客户端的部分所述,Hazelcast 节点提供一个 REST API。
As described in the section of the documentation that cover other clients, there is a REST API provided by the Hazelcast node(s).
例如,您可以删除单独的密钥,如下所示(务必将 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
替换为 SESSION cookie 的值):
For example, you could delete an individual key as follows (being sure to replace 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
with the value of your SESSION cookie):
$ curl -v -X DELETE http://localhost:xxxxx/hazelcast/rest/maps/spring:session:sessions/7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
Hazelcast 节点的端口号会在启动时打印到控制台中。使用端口号替换`xxxxx`。 |
The port number of the Hazelcast node is printed to the console on startup. Replace |
现在,您可以看到,您不再通过该会话进行验证。
Now you can see that you are no longer authenticated with this session.
How HttpSession
Integration Works
幸运的是,HttpSession
和 HttpServletRequest
(用于获取一个 HttpSession
的 API)都是接口。这意味着我们为每个 API 提供我们自己的实现。
Fortunately, both HttpSession
and HttpServletRequest
(the API for obtaining an HttpSession
) are both interfaces.
This means that we can provide our own implementations for each of these APIs.
本节介绍了 Spring Session 如何提供与 |
This section describes how Spring Session provides transparent integration with |
首先,我们创建一个自定义的 HttpServletRequest
,它返回一个 HttpSession
的自定义实现。它看起来类似于以下内容:
First, we create a custom HttpServletRequest
that returns a custom implementation of HttpSession
.
It looks something like the following:
public class SessionRepositoryRequestWrapper extends HttpServletRequestWrapper {
public SessionRepositoryRequestWrapper(HttpServletRequest original) {
super(original);
}
public HttpSession getSession() {
return getSession(true);
}
public HttpSession getSession(boolean createNew) {
// create an HttpSession implementation from Spring Session
}
// ... other methods delegate to the original HttpServletRequest ...
}
返回一个 HttpSession
的任何方法都会被覆盖。所有其他方法都由 HttpServletRequestWrapper
实现,并且委托给原始的 HttpServletRequest
实现。
Any method that returns an HttpSession
is overridden.
All other methods are implemented by HttpServletRequestWrapper
and delegate to the original HttpServletRequest
implementation.
我们通过使用名为 SessionRepositoryFilter
的 Servlet Filter
替换 HttpServletRequest
实现。以下伪代码显示了它的工作原理:
We replace the HttpServletRequest
implementation by using a servlet Filter
called SessionRepositoryFilter
.
The following pseudocode shows how it works:
public class SessionRepositoryFilter implements Filter {
public doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
HttpServletRequest httpRequest = (HttpServletRequest) request;
SessionRepositoryRequestWrapper customRequest =
new SessionRepositoryRequestWrapper(httpRequest);
chain.doFilter(customRequest, response, chain);
}
// ...
}
通过将一个自定义 HttpServletRequest
实现传递到 FilterChain
,我们确保在我们的 Filter
之后调用的任何内容都使用自定义 HttpSession
实现。这突出了将 Spring 会话的 SessionRepositoryFilter
放在与 HttpSession
交互的任何内容之前非常重要的原因。
By passing a custom HttpServletRequest
implementation into the FilterChain
, we ensure that anything invoked after our Filter
uses the custom HttpSession
implementation.
This highlights why it is important that Spring Session’s SessionRepositoryFilter
be placed before anything that interacts with the HttpSession
.
HttpSession
and RESTful APIs
Spring 会话可以通过让会话在标题中提供来处理 RESTful API。
Spring Session can work with RESTful APIs by letting the session be provided in a header.
REST Sample 提供了一个工作示例,演示如何在 REST 应用程序中使用 Spring Session 以支持通过标头进行身份验证。在接下来的部分中,你可以按照所述的基本整合步骤进行操作,但是我们建议你在与自己的应用程序整合时使用详细的 REST 指南。 |
The REST Sample provides a working sample of how to use Spring Session in a REST application to support authenticating with a header. You can follow the basic steps for integration described in the next few sections, but we encourage you to follow along with the detailed REST Guide when integrating with your own application. |
@18
Spring Session - REST
Rob Winch
本指南介绍了如何在使用 REST 端点时使用 Spring Session 将 Redis 透明地利用为 Web 应用程序的 HttpSession
提供支持。
This guide describes how to use Spring Session to transparently leverage Redis to back a web application’s HttpSession
when you use REST endpoints.
您可以在 rest sample application 中找到已完成的指南。 |
You can find the completed guide in the rest-sample. |
Updating Dependencies
在使用 Spring 会话之前,您必须更新依赖。如果您使用 Maven,您必须添加以下依赖:
Before you use Spring Session, you must update your dependencies. If you use Maven, you must add the following dependencies:
<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 配置:
After adding the required dependencies, we can create our Spring configuration.
The Spring configuration is responsible for creating a servlet filter that replaces the HttpSession
implementation with an implementation backed by Spring Session.
To do so, add the following Spring Configuration:
Unresolved include directive in modules/ROOT/pages/guides/java-rest.adoc - include::example$spring-session-samples/spring-session-sample-javaconfig-rest/src/main/java/sample/HttpSessionConfig.java[]
1 | The @EnableRedisHttpSession annotation creates a Spring bean named springSessionRepositoryFilter that implements Filter .
The filter is in charge of replacing the HttpSession implementation to be backed by Spring Session.
In this instance, Spring Session is backed by Redis. |
2 | We create a RedisConnectionFactory that connects Spring Session to the Redis Server.
We configure the connection to connect to localhost on the default port (6379).
For more information on configuring Spring Data Redis, see the {docs-url}/spring-data/data-redis/docs/{spring-data-redis-version}/reference/html/[reference documentation]. |
3 | We customize Spring Session’s HttpSession integration to use HTTP headers to convey the current session information instead of cookies. |
Servlet Container Initialization
我们的 Spring Configuration 创建了一个名为 springSessionRepositoryFilter
的 Spring Bean,它实现了 Filter
。springSessionRepositoryFilter
Bean 负责使用由 Spring 会话支持的自定义实现来替换 HttpSession
。
Our rest-spring-configuration created a Spring Bean named springSessionRepositoryFilter
that implements Filter
.
The springSessionRepositoryFilter
bean is responsible for replacing the HttpSession
with a custom implementation that is backed by Spring Session.
为了让我们的 Filter
发挥作用,Spring 需要加载我们的 Config
类。我们在 Spring MvcInitializer
中提供配置,如下面的示例所示:
In order for our Filter
to do its magic, Spring needs to load our Config
class.
We provide the configuration in our Spring MvcInitializer
, as the following example shows:
Unresolved include directive in modules/ROOT/pages/guides/java-rest.adoc - include::example$spring-session-samples/spring-session-sample-javaconfig-rest/src/main/java/sample/mvc/MvcInitializer.java[]
最后,我们需要确保我们的 Servlet 容器(即 Tomcat)对每个请求使用我们的 springSessionRepositoryFilter
。幸运的是,Spring 会话提供了一个名为 AbstractHttpSessionApplicationInitializer
的实用程序类,使此操作变得简单。为此,使用默认构造函数扩展该类,如下面的示例所示:
Last, we need to ensure that our Servlet Container (that is, Tomcat) uses our springSessionRepositoryFilter
for every request.
Fortunately, Spring Session provides a utility class named AbstractHttpSessionApplicationInitializer
that makes doing so easy. To do so, extend the class with the default constructor, as the following example shows:
Unresolved include directive in modules/ROOT/pages/guides/java-rest.adoc - include::example$spring-session-samples/spring-session-sample-javaconfig-rest/src/main/java/sample/Initializer.java[]
我们的类 ( |
The name of our class ( |
rest
Sample Application
本部分介绍如何使用 rest
样本应用程序。
This section describes how to use the rest
sample application.
Running the rest
Sample Application
您可以获取 源代码 并调用以下命令运行示例:
You can run the sample by obtaining the source code and invoking the following command:
要让示例发挥作用,你必须在 localhost 上 install Redis 2.8+ 并使用默认端口 (6379) 运行它。或者,你可以更新 |
For the sample to work, you must install Redis 2.8+ on localhost and run it with the default port (6379).
Alternatively, you can update the |
$ ./gradlew :spring-session-sample-javaconfig-rest:tomcatRun
您现在应该能够访问 [role="bare"][role="bare"]http://localhost:8080/ 中的应用程序。
You should now be able to access the application at [role="bare"]http://localhost:8080/
Exploring the rest
Sample Application
你现在可以尝试使用该应用。要执行此操作,请使用你喜爱的 REST 客户端请求 [role="bare"][role="bare"]http://localhost:8080/。
You can now try to use the application. To do so, use your favorite REST client to request [role="bare"]http://localhost:8080/
$ curl -v http://localhost:8080/
请注意,系统会提示您进行基本认证。提供以下用户名和密码信息:
Note that you are prompted for basic authentication. Provide the following information for the username and password:
-
Username user
-
Password password
然后,运行以下命令:
Then run the following command:
$ curl -v http://localhost:8080/ -u user:password
在输出中,您应会看到以下内容:
In the output, you should notice the following:
HTTP/1.1 200 OK ... X-Auth-Token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3 {"username":"user"}
具体来说,您应该注意我们响应的以下内容:
Specifically, you should notice the following things about our response:
-
The HTTP Status is now a 200.
-
We have a header a the name of
X-Auth-Token
and that contains a new session ID. -
The current username is displayed.
我们现在可以使用 X-Auth-Token
再次提出请求而无需再次提供用户名和密码。例如,如下命令输出了用户名,与之前一样:
We can now use the X-Auth-Token
to make another request without providing the username and password again. For example, the following command outputs the username, as before:
$ curl -v http://localhost:8080/ -H "X-Auth-Token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"
唯一的区别是会话 ID 未在响应头中提供,因为我们正在重复使用现有的会话。
The only difference is that the session ID is not provided in the response headers because we are reusing an existing session.
如果我们使会话失效,X-Auth-Token
会显示在响应中,并附带一个空值。例如,如下命令使我们的会话失效:
If we invalidate the session, the X-Auth-Token
is displayed in the response with an empty value. For example, the following command invalidates our session:
$ curl -v http://localhost:8080/logout -H "X-Auth-Token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"
在输出中,您可以看到 X-Auth-Token
提供了一个空 String
,表明上一个会话已失效:
You can see in the output that the X-Auth-Token
provides an empty String
indicating that the previous session was invalidated:
HTTP/1.1 204 No Content ... X-Auth-Token:
How Does It Work?
Spring Security 与 SecurityContextPersistenceFilter
中的标准 HttpSession
交互。
Spring Security interacts with the standard HttpSession
in SecurityContextPersistenceFilter
.
现在,Spring Security 正在持久保留 Redis 中的值,而非使用 Tomcat 的 HttpSession
。Spring Session 在浏览器中创建了一个名为 X-Auth-Token
的 header。该 header 包含会话的 ID。
Instead of using Tomcat’s HttpSession
, Spring Security is now persisting the values in Redis.
Spring Session creates a header named X-Auth-Token
in your browser.
That header contains the ID of your session.
如果您愿意,您可以轻松地看到会话是在 Redis 中创建的。为此,通过使用如下命令创建会话:
If you like, you can easily see that the session is created in Redis. To do so, create a session by using the following command:
$ curl -v http://localhost:8080/ -u user:password
在输出中,您应会看到以下内容:
In the output, you should notice the following:
HTTP/1.1 200 OK ... X-Auth-Token: 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e {"username":"user"}
现在,您可以通过使用 redis-cli 删除会话。例如,在基于 Linux 的系统上,您可以输入:
Now you can remove the session by using redis-cli. For example, on a Linux based system, you can type:
$ redis-cli keys '*' | xargs redis-cli del
Redis 文档包含有关 installing redis-cli 的说明。 |
The Redis documentation has instructions for installing redis-cli. |
或者,您还可以删除显式密钥。为此,请将以下内容输入到您的终端中,确保将 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
替换为 SESSION
cookie 的值:
Alternatively, you can also delete the explicit key.
To do so, enter the following into your terminal, being sure to replace 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
with the value of your SESSION
cookie:
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
现在,我们可以使用 X-Auth-Token
对我们已删除的会话发出另一个请求,并观察到我们被提示进行身份验证。例如,如下命令返回一个 HTTP 401:
We can now use the X-Auth-Token
to make another request with the session we deleted and observe we that are prompted for authentication. For example, the following returns an HTTP 401:
$ curl -v http://localhost:8080/ -H "X-Auth-Token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"
Using HttpSessionListener
Spring 会话通过将 SessionDestroyedEvent
和 SessionCreatedEvent
转换为 HttpSessionEvent
,并声明 SessionEventHttpSessionListenerAdapter
来支持 HttpSessionListener
。要使用此支持,您需要:
Spring Session supports HttpSessionListener
by translating SessionDestroyedEvent
and SessionCreatedEvent
into HttpSessionEvent
by declaring SessionEventHttpSessionListenerAdapter
.
To use this support, you need to:
-
Ensure your
SessionRepository
implementation supports and is configured to fireSessionDestroyedEvent
andSessionCreatedEvent
. -
Configure
SessionEventHttpSessionListenerAdapter
as a Spring bean. -
Inject every
HttpSessionListener
into theSessionEventHttpSessionListenerAdapter
如果您使用 Redis 支持,将 enableIndexingAndEvents
设置为 true
、@EnableRedisHttpSession(enableIndexingAndEvents = true)
,您所要做的就是将每个 HttpSessionListener
注册为一个 Bean。例如,假设您希望支持 Spring Security 的并发控制,并且需要使用 HttpSessionEventPublisher
。在这种情况下,您可以将 HttpSessionEventPublisher
添加为一个 Bean。在 Java 配置中,这可能如下所示:
If you use the Redis support with enableIndexingAndEvents
set to true
, @EnableRedisHttpSession(enableIndexingAndEvents = true)
, all you need to do is register every HttpSessionListener
as a bean.
For example, assume you want to support Spring Security’s concurrency control and need to use HttpSessionEventPublisher
. In that case, you can add HttpSessionEventPublisher
as a bean.
In Java configuration, this might look like the following:
/*
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package docs.http;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
// tag::config[]
@Configuration
@EnableRedisHttpSession
public class RedisHttpSessionConfig {
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
// ...
}
// end::config[]
在 XML 配置中,这可能如下所示:
In XML configuration, this might look like the following:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util-4.1.xsd">
<!-- tag::config[] -->
<bean class="org.springframework.security.web.session.HttpSessionEventPublisher"/>
<!-- end::config[] -->
<context:annotation-config/>
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisIndexedHttpSessionConfiguration"/>
<bean class="docs.http.AbstractHttpSessionListenerTests"
factory-method="createMockRedisConnection"/>
<bean class="docs.http.AbstractHttpSessionListenerTests$SecuritySessionDestroyedListener"/>
</beans>