提交 48d04a5e 编写于 作者: 茶陵後's avatar 茶陵後 👍

#19 spring session 文案优化

上级 269fc6eb
......@@ -77,7 +77,7 @@ module.exports = {
plugins: [
['autometa', autometa_options]
],
theme: path.resolve(__dirname,'./themes/theme-gitcode/index.js'),
theme: path.resolve(__dirname, './themes/theme-gitcode/index.js'),
themeConfig: {
repo: "https://gitcode.net/dev-cloud/spring",
repoLabel: "GitCode",
......@@ -266,7 +266,7 @@ module.exports = {
// initialOpenGroupIndex: 0 // 可选的, 默认值是 0
// }
// ],
// // fallback
// '/en/':
// [{
......@@ -357,29 +357,28 @@ module.exports = {
text: '更多文档',
ariaLabel: 'Others',
items: [
{ text: 'Spring Cloud Data Flow', link: '/spring-cloud-data-flow/'},
{ text: 'Spring Security', link: '/spring-security/'},
{ text: 'Spring for GraphQL', link: '/spring-for-graphql/'},
{ text: 'Spring Session', link: '/spring-session/'},
{ text: 'Spring Integration', link: '/spring-integration/'},
{ text: 'Spring HATEOAS', link: '/spring-hateoas/'},
{ text: 'Spring REST Docs', link: '/spring-rest-docs/'},
{ text: 'Spring Batch', link: '/spring-batch/'},
{ text: 'Spring AMQP', link: '/spring-amqp/'},
{ text: 'Spring CredHub', link: '/spring-credhub/'},
{ text: 'Spring Flo', link: '/spring-flo/'},
{ text: 'Spring for Apache Kafka', link: '/spring-for-apache-kafka/'},
{ text: 'Spring LDAP', link: '/spring-ldap/'},
{ text: 'Spring Shell', link: '/spring-shell/'},
{ text: 'Spring Statemachine', link: '/spring-statemachine/'},
{ text: 'Spring Vault', link: '/spring-vault/'},
{ text: 'Spring Web Flow', link: '/spring-web-flow/'},
{ text: 'Spring Web Services', link: '/spring-web-services/'}
{ text: 'Spring Cloud Data Flow', link: '/spring-cloud-data-flow/' },
{ text: 'Spring Security', link: '/spring-security/' },
{ text: 'Spring for GraphQL', link: '/spring-for-graphql/' },
{ text: 'Spring Session', link: '/spring-session/' },
{ text: 'Spring Integration', link: '/spring-integration/' },
{ text: 'Spring HATEOAS', link: '/spring-hateoas/' },
{ text: 'Spring REST Docs', link: '/spring-rest-docs/' },
{ text: 'Spring Batch', link: '/spring-batch/' },
{ text: 'Spring AMQP', link: '/spring-amqp/' },
{ text: 'Spring CredHub', link: '/spring-credhub/' },
{ text: 'Spring Flo', link: '/spring-flo/' },
{ text: 'Spring for Apache Kafka', link: '/spring-for-apache-kafka/' },
{ text: 'Spring LDAP', link: '/spring-ldap/' },
{ text: 'Spring Shell', link: '/spring-shell/' },
{ text: 'Spring Statemachine', link: '/spring-statemachine/' },
{ text: 'Spring Vault', link: '/spring-vault/' },
{ text: 'Spring Web Flow', link: '/spring-web-flow/' },
{ text: 'Spring Web Services', link: '/spring-web-services/' }
]
}
],
],
sidebar: {
'/spring-boot/': [
{
title: 'Spring Boot 文档',
......@@ -510,6 +509,108 @@ module.exports = {
initialOpenGroupIndex: 0 // 可选的, 默认值是 0
}
],
'/spring-session/': [
{
title: 'Spring Session 文档',
sidebarDepth: 2,
collapsable: false,
children: [
"/spring-session/_index.md",
"/spring-session/whats-new.md",
"/spring-session/samples.md",
"/spring-session/bootSamples/HttpSession/mongo.md",
"/spring-session/bootSamples/HttpSession/jdbc.md",
"/spring-session/bootSamples/HttpSession/Redis/boot-redis.md",
"/spring-session/bootSamples/boot-findbyusername.md",
"/spring-session/bootSamples/boot-websocket.md",
"/spring-session/webFlux/boot-webflux-custom-cookie.md",
"/spring-session/modules.md",
"/spring-session/http-session.md",
"/spring-session/web-socket.md",
"/spring-session/web-session.md",
"/spring-session/spring-security.md",
"/spring-session/api.md",
"/spring-session/upgrading.md"
],
initialOpenGroupIndex: 0 // 可选的, 默认值是 0
}
],
'/spring-session/sample/': [
{
title: 'Spring Session 文档3',
sidebarDepth: 2,
collapsable: false,
children: [
"/spring-session/sample/samples.md"
],
initialOpenGroupIndex: 0 // 可选的, 默认值是 0
}
],
'/spring-integration/': [
{
title: 'Spring Integration 文档',
sidebarDepth: 2,
collapsable: false,
children: [
"/spring-integration/preface.md",
"/spring-integration/whats-new.md",
"/spring-integration/overview.md",
"/spring-integration/core.md",
"/spring-integration/message.md",
"/spring-integration/message-routing.md",
"/spring-integration/message-transformation.md",
"/spring-integration/messaging-endpoints.md",
"/spring-integration/dsl.md",
"/spring-integration/kotlin-dsl.md",
"/spring-integration/system-management.md",
"/spring-integration/reactive-streams.md",
"/spring-integration/endpoint-summary.md",
"/spring-integration/amqp.md",
"/spring-integration/event.md",
"/spring-integration/feed.md",
"/spring-integration/file.md",
"/spring-integration/ftp.md",
"/spring-integration/gemfire.md",
"/spring-integration/http.md",
"/spring-integration/jdbc.md",
"/spring-integration/jpa.md",
"/spring-integration/jms.md",
"/spring-integration/jmx.md",
"/spring-integration/kafka.md",
"/spring-integration/mail.md",
"/spring-integration/mongodb.md",
"/spring-integration/mqtt.md",
"/spring-integration/r2dbc.md",
"/spring-integration/redis.md",
"/spring-integration/resource.md",
"/spring-integration/rmi.md",
"/spring-integration/rsocket.md",
"/spring-integration/sftp.md",
"/spring-integration/stomp.md",
"/spring-integration/stream.md",
"/spring-integration/syslog.md",
"/spring-integration/ip.md",
"/spring-integration/webflux.md",
"/spring-integration/web-sockets.md",
"/spring-integration/ws.md",
"/spring-integration/xml.md",
"/spring-integration/xmpp.md",
"/spring-integration/zeromq.md",
"/spring-integration/zookeeper.md",
"/spring-integration/error-handling.md",
"/spring-integration/spel.md",
"/spring-integration/message-publishing.md",
"/spring-integration/transactions.md",
"/spring-integration/security.md",
"/spring-integration/configuration.md",
"/spring-integration/testing.md",
"/spring-integration/samples.md",
"/spring-integration/resources.md",
"/spring-integration/history.md"
],
initialOpenGroupIndex: 0 // 可选的, 默认值是 0
}
],
'/spring-hateoas/': [
{
title: 'Spring HATEOAS 文档',
......@@ -687,7 +788,7 @@ module.exports = {
}
],
// fallback
'/':
'/':
[{
title: 'Spring 文档', // 必要的
// path: '/', // 可选的, 标题的跳转链接,应为绝对路径且必须存在
......@@ -740,7 +841,7 @@ module.exports = {
],
initialOpenGroupIndex: 0 // 可选的, 默认值是 0
}
]
]
}
}
}
......
# Spring Session
\ No newline at end of file
# Spring 会议
Spring Session 提供了用于管理用户的会话信息的 API 和实现。
Spring Session 提供了用于管理用户会话信息的 API 和实现,同时也使得在不绑定到特定于应用程序容器的解决方案的情况下支持群集会话变得非常简单。它还提供了以下方面的透明整合:
* [HttpSession ](http-session.html#httpsession):允许以与应用程序容器无关的方式替换`HttpSession`,并支持在头文件中提供会话 ID,以便与 RESTful API 一起工作。
* [WebSocket](web-socket.html#websocket):提供了在接收 WebSocket 消息时保持`HttpSession`活动的能力
* [WebSession](web-session.html#websession):允许以与应用程序容器无关的方式替换 Spring WebFlux 的`WebSession`
## Spring Session 社区
我们 GLAD 将你视为我们社区的一部分。以下各节提供了有关如何与 Spring Session 社区交互的更多信息。
### 支持
你可以通过在[stack overflow with`spring-session`tag](https://stackoverflow.com/questions/tagged/ Spring-session)上提问来获得帮助。同样,我们通过回答有关 Stack Overflow 的问题来鼓励帮助他人。
### 源代码
你可以在 Github 上找到源代码,网址为[https://github.com/spring-projects/spring-session/](https://github.com/spring-projects/spring-session/)
### 问题跟踪
我们在[https://github.com/spring-projects/spring-session/issues](https://github.com/spring-projects/spring-session/issues)上跟踪 GitHub 问题
### 贡献
我们感谢[拉请求](https://help.github.com/articles/using-pull-requests/)
### 许可证
Spring Session 是在[Apache2.0 许可证](https://www.apache.org/licenses/LICENSE-2.0)下发布的开源软件。
### 社区扩展
| Name |位置|
|-------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|Spring Session Infinispan|[https://infinispan.org/infinispan-spring-boot/master/spring\_boot\_starter.html#\_enabling\_spring\_session\_support](https://infinispan.org/infinispan-spring-boot/master/spring_boot_starter.html#_enabling_spring_session_support)|
## 最低要求
Spring 场会议的最低要求是:
* Java8+。
* 如果你在 Servlet 容器中运行(不是必需的),则 Servlet 3.1+。
* 如果使用其他 Spring 库(不是必需的),则所需的最低版本是 Spring 5.0.x。
* `@EnableRedisHttpSession`需要 Redis2.8+。这是支持[会话过期](api.html#api-redisindexedsessionrepository-expiration)所必需的
* `@EnableHazelcastHttpSession`需要 HazelCast3.6+。这是支持[`FindByIndexNameSessionRepository`]所必需的(api.html#api-enablehazelcasthtpsession-storage)
| |在其核心, Spring Session 仅对`spring-jcl`具有所需的依赖关系。<br/>关于使用 Spring Session 而不使用任何其他 Spring 依赖关系的示例,请参见[Hazelcast 样品](samples.html#samples)应用程序。|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
\ No newline at end of file
此差异已折叠。
# Spring Session- Spring Boot
本指南描述了在使用 Spring 引导时如何使用 Spring Session 透明地利用 Redis 来支持 Web 应用程序的`HttpSession`
| |你可以在[引导示例应用程序](#boot-sample)中找到完整的指南。|
|---|--------------------------------------------------------------------------------|
[Index](../index.html)
## 更新依赖项
在使用 Spring Session 之前,你必须确保你的依赖关系。我们假设你正在使用一个有效的启动 Web 应用程序。如果正在使用 Maven,则必须添加以下依赖项:
POM.xml
```
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
</dependencies>
```
Spring 启动为 Spring Session 模块提供了依赖管理,因此不需要显式声明依赖版本。
## Spring 引导配置
在添加了所需的依赖项之后,我们就可以创建我们的 Spring 启动配置了。多亏了一流的自动配置支持,由 Redis 支持的设置 Spring Session 非常简单,只需向你的`application.properties`添加一个配置属性,如以下清单所示:
SRC/主/资源/应用程序.properties
```
spring.session.store-type=redis # Session store type.
```
在这种情况下, Spring boot 应用的配置相当于手动添加`@EnableRedisHttpSession`注释。这将创建一个名为`springSessionRepositoryFilter`的 Spring Bean,实现`Filter`。过滤器负责替换要由 Spring Session 支持的`HttpSession`实现。
使用`application.properties`还可以进行进一步的定制,如以下清单所示:
SRC/主/资源/应用程序.properties
```
server.servlet.session.timeout= # Session timeout. If a duration suffix is not specified, seconds is used.
spring.session.redis.flush-mode=on_save # Sessions flush mode.
spring.session.redis.namespace=spring:session # Namespace for keys used to store sessions.
```
有关更多信息,请参见 Spring 引导文档的[Spring Session](https://docs.spring.io/spring-boot/docs/2.5.6/reference/htmlsingle/#boot-features-session)部分。
## 配置 Redis 连接
Spring 启动会自动创建一个`RedisConnectionFactory`,它将 Spring Session 连接到端口 6379(默认端口)上本地主机上的 Redis 服务器。在生产环境中,你需要更新配置以指向 Redis 服务器。例如,你可以在应用程序中包含以下内容:
SRC/主/资源/应用程序.properties
```
spring.redis.host=localhost # Redis server host.
spring.redis.password= # Login password of the redis server.
spring.redis.port=6379 # Redis server port.
```
有关更多信息,请参见 Spring 引导文档的[连接到 Redis](https://docs.spring.io/spring-boot/docs/2.5.6/reference/htmlsingle/#boot-features-connecting-to-redis)部分。
## Servlet 容器初始化
我们的[Spring Boot Configuration](#boot-spring-configuration)创建了一个名为`springSessionRepositoryFilter`的 Spring Bean,它实现了`Filter``springSessionRepositoryFilter` Bean 负责用 Spring Session 支持的自定义实现替换`HttpSession`
为了使我们的`Filter`发挥其魔力, Spring 需要加载我们的`Config`类。最后,我们需要确保我们的 Servlet 容器(即 Tomcat)为每个请求使用我们的`springSessionRepositoryFilter`。幸运的是,Boot 为我们解决了这两个步骤。
## 引导示例应用程序
引导示例应用程序演示了如何在使用 Spring 引导时使用 Spring Session 透明地利用 Redis 来支持 Web 应用程序的`HttpSession`
### 运行引导示例应用程序
你可以通过获取[源代码](https://github.com/spring-projects/spring-session/archive/main.zip)并调用以下命令来运行示例:
```
$ ./gradlew :spring-session-sample-boot-redis:bootRun
```
| |要使示例工作,你必须在 localhost 上[安装 Redis2.8+](https://redis.io/download)并使用默认端口(6379)运行它。<br/>或者,你可以更新`RedisConnectionFactory`以指向 Redis 服务器。<br/>另一个选项是使用[Docker](https://www.docker.com/)在 localhost 上运行 Redis。详细说明见[Docker Redis 存储库](https://hub.docker.com/_/redis/)。|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
现在你应该可以在[http://localhost:8080/](http://localhost:8080/)上访问应用程序了。
### 探索`security`示例应用程序
现在你可以尝试使用该应用程序了。输入以下内容即可登录:
* **用户 Name** *User*
* **密码** *密码*
现在点击**登录**按钮。你现在应该会看到一条消息,表明你是用先前输入的用户登录的。用户的信息存储在 Redis 中,而不是 Tomcat 的`HttpSession`实现中。
### 它是如何工作的?
我们不使用 Tomcat 的`HttpSession`,而是在 Redis 中保存这些值。 Spring Session 用一个由 Redis 支持的实现替换`HttpSession`。当 Spring Security 的`SecurityContextPersistenceFilter``SecurityContext`保存到`HttpSession`时,它将被持久化到 Redis 中。
当创建一个新的`HttpSession`时, Spring Session 将在浏览器中创建一个名为`SESSION`的 cookie。该 cookie 包含你的会话的 ID。你可以查看 cookies(使用[Chrome](https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies)[Firefox](https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector))。
你可以使用 redis-cli 删除会话。例如,在基于 Linux 的系统上,你可以键入以下内容:
```
$ redis-cli keys '*' | xargs redis-cli del
```
| |Redis 文档中有[安装 Redis-CLI](https://redis.io/topics/quickstart)的说明。|
|---|--------------------------------------------------------------------------------------------------------|
或者,你也可以删除显式密钥。要这样做,请在终端中输入以下内容,并确保将`7e8383a4-082c-4ffe-a4bc-c40fd3363c5e`替换为`SESSION`cookie 的值:
```
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
```
现在,你可以访问[http://localhost:8080/](http://localhost:8080/)上的应用程序,并观察到我们不再经过身份验证。
\ No newline at end of file
# Spring Session- Spring 启动
本指南描述了在使用 Spring 引导时如何使用 Spring Session 来透明地利用关系数据库来支持 Web 应用程序的`HttpSession`
| |你可以在[httpsession-jdbc-boot 示例应用程序](#httpsession-jdbc-boot-sample)中找到完整的指南。|
|---|------------------------------------------------------------------------------------------------------------------|
[Index](../index.html)
## 更新依赖项
在使用 Spring Session 之前,你必须更新你的依赖关系。我们假设你正在使用一个有效的启动 Web 应用程序。如果使用 Maven,则必须添加以下依赖项:
POM.xml
```
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
</dependency>
</dependencies>
```
Spring 启动为 Spring Session 模块提供了依赖管理,因此不需要显式地声明依赖版本。
## Spring 引导配置
在添加了所需的依赖项之后,我们就可以创建我们的 Spring 启动配置了。多亏了一流的自动配置支持,在关系数据库支持下设置 Spring Session 就像在`application.properties`中添加一个配置属性一样简单。下面的清单展示了如何做到这一点:
SRC/主/资源/应用程序.properties
```
spring.session.store-type=jdbc # Session store type.
```
如果在 Classpath 上存在单个 Spring Session 模块,则 Spring 引导将自动使用该存储实现。如果有多个实现,则必须选择要用来存储会话的 StoreType,如上面所示。
在这种情况下, Spring boot 应用的配置相当于手动添加`@EnableJdbcHttpSession`注释。这将创建一个名为`springSessionRepositoryFilter`的 Spring Bean。 Bean 实现`Filter`。过滤器负责替换要由 Spring Session 支持的`HttpSession`实现。
你可以使用`application.properties`来进一步自定义。下面的清单展示了如何做到这一点:
SRC/主/资源/应用程序.properties
```
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/[email protected]@[email protected]@.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 引导文档的[Spring Session](https://docs.spring.io/spring-boot/docs/2.5.6/reference/htmlsingle/#boot-features-session)部分。
## 配置`DataSource`
Spring 引导会自动创建一个`DataSource`,它将 Spring Session 连接到 H2 数据库的嵌入式实例。在生产环境中,你需要更新配置以指向关系数据库。例如,你可以在应用程序中包含以下内容:
SRC/主/资源/应用程序.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 引导文档的[配置数据源](https://docs.spring.io/spring-boot/docs/2.5.6/reference/htmlsingle/#boot-features-configure-datasource)部分。
## Servlet 容器初始化
我们的[Spring Boot Configuration](#httpsession-jdbc-boot-spring-configuration)创建了一个名为`springSessionRepositoryFilter`的 Spring Bean,它实现了`Filter``springSessionRepositoryFilter` Bean 负责用 Spring Session 支持的自定义实现替换`HttpSession`
为了让我们的`Filter`发挥其魔力, Spring 需要加载我们的`Config`类。最后,我们需要确保我们的 Servlet 容器(即 Tomcat)为每个请求使用我们的`springSessionRepositoryFilter`。幸运的是,Boot 为我们解决了这两个步骤。
## `httpsession-jdbc-boot`示例应用程序
HttpSession-JDBC-Boot 示例应用程序演示了如何在使用 Spring 引导时使用 Spring Session 透明地利用 H2 数据库来支持 Web 应用程序的`HttpSession`
### 运行`httpsession-jdbc-boot`示例应用程序
你可以通过获取[源代码](https://github.com/spring-projects/spring-session/archive/main.zip)并调用以下命令来运行示例:
```
$ ./gradlew :spring-session-sample-boot-jdbc:bootRun
```
现在你应该可以在[http://localhost:8080/](http://localhost:8080/)上访问应用程序了。
### 探索安全示例应用程序
你现在可以尝试使用该应用程序了。要这样做,请输入以下内容以进行登录:
* **用户 Name** *User*
* **密码** *密码*
现在点击**登录**按钮。你现在应该会看到一条消息,该消息指示你是用先前输入的用户登录的。用户的信息存储在 H2 数据库中,而不是 Tomcat 的`HttpSession`实现。
### 它是如何工作的?
我们不使用 Tomcat 的`HttpSession`,而是将这些值保存在 H2 数据库中。 Spring Session 使用由关系数据库支持的实现来替换`HttpSession`。当 Spring Security 的`SecurityContextPersistenceFilter``SecurityContext`保存到`HttpSession`时,它将被持久化到 H2 数据库中。
当创建一个新的`HttpSession`时, Spring Session 将在浏览器中创建一个名为`SESSION`的 cookie。该 cookie 包含你的会话的 ID。你可以查看 cookies(使用[Chrome](https://developers.google.com/web/tools/chrome-devtools/manage-data/cookies)[Firefox](https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector))。
你可以通过使用 H2Web 控制台来删除会话:[http://localhost:8080/h2-console/](http://localhost:8080/h2-console/)(对于 JDBC URL 使用`jdbc:h2:mem:testdb`)。
现在,你可以访问[http://localhost:8080/](http://localhost:8080/)上的应用程序,并看到我们不再经过身份验证。
\ No newline at end of file
# Spring Session-MongoDB 存储库
本指南描述了如何使用由 MongoDB 支持的 Spring Session 。
| |完整的指南可在[Mongo 示例应用程序](#mongo-sample)中找到。|
|---|----------------------------------------------------------------------------------|
[Index](../index.html)
## 更新依赖项
在使用 Spring Session MongoDB 之前,必须确保更新依赖项。我们假设你正在使用一个有效的启动 Web 应用程序。如果你正在使用 Maven,请确保添加以下依赖项:
POM.xml
```
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-mongodb</artifactId>
</dependency>
</dependencies>
```
由于我们使用的是快照版本,因此我们需要确保添加 Spring 快照 Maven 存储库。确保在 POM.xml 中包含以下内容:
POM.xml
```
<repositories>
<!-- ... -->
<repository>
<id>spring-snapshot</id>
<url>https://repo.spring.io/libs-snapshot</url>
</repository>
</repositories>
```
## Spring 配置
在添加了所需的依赖关系之后,我们就可以创建我们的 Spring 配置了。 Spring 配置负责创建一个 Servlet 过滤器,该过滤器将`HttpSession`实现替换为由 Spring Session 支持的实现。
你所要做的就是添加以下 Spring 配置:
```
@EnableMongoHttpSession (1)
public class HttpSessionConfig {
@Bean
public JdkMongoSessionConverter jdkMongoSessionConverter() {
return new JdkMongoSessionConverter(Duration.ofMinutes(30)); (2)
}
}
```
|**1**|`@EnableMongoHttpSession`注释创建了一个名为`springSessionRepositoryFilter`的 Spring Bean,它实现了 filter。<br/>这个 filter 用 MongoDB 支持的 Bean 替换了默认的`HttpSession`。|
|-----|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|**2**|将会话超时时间配置为 30 分钟。|
## 配置 MongoDB 连接
Spring 引导会自动创建一个`MongoClient`,它将 Spring Session 连接到端口 27017(默认端口)上的 LocalHost 上的 MongoDB 服务器。在生产环境中,你需要确保更新配置以指向 MongoDB 服务器。例如,你可以在**应用程序.属性**中包含以下内容
SRC/主/资源/应用程序.properties
```
spring.data.mongodb.host=mongo-srv
spring.data.mongodb.port=27018
spring.data.mongodb.database=prod
```
有关更多信息,请参阅 Spring 引导文档的[连接到 MongoDB](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-connecting-to-mongodb)部分。
## Servlet 容器初始化
我们的[Spring Configuration](#boot-mongo-configuration)创建了一个名为`springSessionRepositoryFilter`的 Spring Bean,它实现了`Filter``springSessionRepositoryFilter` Bean 负责用 Spring Session 支持的自定义实现替换`HttpSession`
为了让我们的`Filter`发挥其魔力, Spring 需要加载我们的`Config`类。最后,我们需要确保我们的 Servlet 容器(即 Tomcat)对每个请求使用我们的`springSessionRepositoryFilter`。幸运的是,Boot 为我们解决了这两个步骤。
## MongoDB 示例应用程序
MongoDB 示例应用程序演示了如何在使用 Spring 引导时使用 Spring Session 透明地利用 MongoDB 来支持 Web 应用程序的`HttpSession`
### 运行 MongoDB 示例应用程序
你可以通过获取[源代码](https://github.com/spring-projects/spring-session/archive/main.zip)并调用以下命令来运行示例:
```
$ ./gradlew :samples:mongo:bootRun
```
现在你应该可以在[http://localhost:8080/](http://localhost:8080/)上访问应用程序了。
### 探索安全示例应用程序
尝试使用该应用程序。输入以下内容即可登录:
* **用户 Name** *User*
* **密码** *密码*
现在点击**登录**按钮。你现在应该会看到一条消息,表明你是用先前输入的用户登录的。用户的信息存储在 MongoDB 中,而不是 Tomcat 的`HttpSession`实现中。
### 它是如何工作的?
而不是使用 Tomcat 的`HttpSession`,我们实际上是在 Mongo 中持久化这些值。 Spring Session 用 Mongo 支持的实现替换`HttpSession`。当 Spring Security 的`SecurityContextPersistenceFilter``SecurityContext`保存到`HttpSession`时,它将被持久化到 Mongo 中。
当创建一个新的`HttpSession`时, Spring Session 将在浏览器中创建一个名为会话的 cookie,其中包含会话的 ID。继续查看 cookies(单击[Chrome](https://developer.chrome.com/devtools/docs/resources#cookies)[Firefox](https://getfirebug.com/wiki/index.php/Cookies_Panel#Cookies_List)以获取帮助)。
如果你愿意,你可以使用 Mongo 客户机轻松地检查会话。例如,在基于 Linux 的系统上,你可以键入:
| |示例应用程序使用了一个嵌入式 MongoDB 实例,该实例监听随机分配的端口。<br/>嵌入式 MongoDB 使用的端口以及用于连接到它的 Exact 命令在应用程序启动时记录。|
|---|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
```
$ mongo --port ...
> use test
> db.sessions.find().pretty()
```
或者,你也可以删除显式密钥。在终端中输入以下内容,以确保用会话 cookie 的值替换`60f17293-839b-477c-bb92-07a9c3658843`:
```
> db.sessions.remove({"_id":"60f17293-839b-477c-bb92-07a9c3658843"})
```
现在访问[http://localhost:8080/](http://localhost:8080/)上的应用程序,并观察到我们不再经过身份验证。
\ No newline at end of file
# Spring Session-按用户名查找
本指南描述了如何使用 Spring Session 通过用户名查找会话。
| |你可以在[FindByUserName 应用程序](#findbyusername-sample)中找到完整的指南。|
|---|---------------------------------------------------------------------------------------------|
[Index](../index.html)
## 假设
该指南假定你已经通过使用内置的 Redis 配置支持向应用程序添加了 Spring Session 。该指南还假定你已经对应用程序应用了 Spring 安全性。然而,我们的指南是有点通用的目的,可以应用于任何技术,只需最小的变化,这一点我们将在后面的指南中进行讨论。
| |如果需要学习如何将 Spring Session 添加到项目中,请参见[样本和指南](../#samples)列表|
|---|--------------------------------------------------------------------------------------------------------------------|
## 关于样本
我们的样例使用此功能使可能受到危害的用户会话无效。考虑以下场景:
* 用户到库并对应用程序进行身份验证。
* 用户回家后发现自己忘了注销。
* 用户可以使用位置、创建时间、最后访问时间等线索从库中登录并结束会话。
如果我们可以让用户在库中的会话从他们用来进行身份验证的任何设备上失效,这不是很好吗?这个示例演示了这是如何实现的。
## 使用`FindByIndexNameSessionRepository`
要通过用户名查找用户,你必须首先选择一个实现[`FindByIndexNameSessionRepository`]的`SessionRepository`。我们的示例应用程序假定已经设置了 Redis 支持,因此我们已经准备好了。
## 映射用户名
`FindByIndexNameSessionRepository`如果开发人员指示 Spring Session 什么用户与`Session`相关联,则只能通过用户名找到会话。你可以通过确保将名称`FindByUsernameSessionRepository.PRINCIPAL_NAME_INDEX_NAME`的会话属性填充为用户名来做到这一点。
一般来说,你可以在用户进行身份验证后立即使用以下代码来完成此操作:
```
String username = "username";
this.session.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, username);
```
## 映射具有 Spring 安全性的用户名
由于我们使用 Spring 安全性,用户名将自动为我们建立索引。这意味着我们不需要执行任何步骤来确保对用户名进行索引。
## 向会话添加附加数据
将附加信息(如 IP 地址、浏览器、位置和其他详细信息)与会话关联起来可能会很好。这样做可以使用户更容易地知道他们正在查看的会话。
要做到这一点,请确定你想要使用的会话属性以及你想要提供的信息。然后创建一个作为会话属性添加的 Java Bean。例如,我们的示例应用程序包括会话的位置和访问类型,如下面的清单所示:
```
public class SessionDetails implements Serializable {
private String location;
private String accessType;
public String getLocation() {
return this.location;
}
public void setLocation(String location) {
this.location = location;
}
public String getAccessType() {
return this.accessType;
}
public void setAccessType(String accessType) {
this.accessType = accessType;
}
private static final long serialVersionUID = 8850489178248613501L;
}
```
然后,我们使用`SessionDetailsFilter`将该信息注入到每个 HTTP 请求的会话中,如下例所示:
```
@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
HttpSession session = request.getSession(false);
if (session != null) {
String remoteAddr = getRemoteAddress(request);
String geoLocation = getGeoLocation(remoteAddr);
SessionDetails details = new SessionDetails();
details.setAccessType(request.getHeader("User-Agent"));
details.setLocation(remoteAddr + " " + geoLocation);
session.setAttribute("SESSION_DETAILS", details);
}
}
```
我们获得我们想要的信息,然后将`SessionDetails`设置为`Session`中的一个属性。当我们通过用户名检索`Session`时,我们可以使用会话来访问我们的`SessionDetails`,就像我们将访问任何其他会话属性一样。
| |你可能想知道为什么 Spring Session 没有提供`SessionDetails`开箱即用的功能。<br/>我们有两个原因。<br/>第一个原因是应用程序自己实现这一点是非常琐碎的。<br/>第二个原因是信息会话中填充的内容(以及信息更新的频率)高度依赖于应用程序。|
|---|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
## 查找特定用户的会话
现在,我们可以为特定用户找到所有会话。下面的示例展示了如何做到这一点:
```
@Autowired
FindByIndexNameSessionRepository<? extends Session> sessions;
@RequestMapping("/")
public String index(Principal principal, Model model) {
Collection<? extends Session> usersSessions = this.sessions.findByPrincipalName(principal.getName()).values();
model.addAttribute("sessions", usersSessions);
return "index";
}
```
在我们的例子中,我们找到了当前登录用户的所有会话。但是,你可以对此进行修改,以便管理员使用表单来指定要查找的用户。
## `findbyusername`示例应用程序
本节介绍如何使用`findbyusername`示例应用程序。
### 运行`findbyusername`示例应用程序
你可以通过获取[源代码](https://github.com/spring-projects/spring-session/archive/main.zip)并调用以下命令来运行示例:
```
$ ./gradlew :spring-session-sample-boot-findbyusername:bootRun
```
| |要使示例工作,你必须在 localhost 上[安装 Redis2.8+](https://redis.io/download)并使用默认端口(6379)运行它。<br/>或者,你可以更新`RedisConnectionFactory`以指向 Redis 服务器。<br/>另一个选项是使用[Docker](https://www.docker.com/)在 localhost 上运行 Redis。<br/>有关详细说明,请参见[Docker Redis 存储库](https://hub.docker.com/_/redis/)。|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
现在你应该可以在[http://localhost:8080/](http://localhost:8080/)上访问应用程序了。
### 探索安全示例应用程序
你现在可以尝试使用该应用程序了。输入以下内容即可登录:
* **用户 Name ** *User *
* **密码** *密码*
现在点击**登录**按钮。你现在应该会看到一条消息,表明你是用先前输入的用户登录的。你还应该看到当前登录用户的活动会话列表。
你可以通过执行以下操作来模拟我们在[关于样本](#_about_the_sample)部分中讨论的流程:
* 打开一个新的隐身窗口并导航到[http://localhost:8080/](http://localhost:8080/)
* 输入以下内容即可登录:
* **用户 Name ** *User *
* **密码** *密码*
* 结束你的原始会话。
* 刷新原始窗口并查看你已注销。
\ No newline at end of file
# Spring Session - WebSocket
本指南描述了如何使用 Spring Session 来确保 WebSocket 消息使你的 HttpSession 保持活跃。
| |Spring session 的 WebSocket 支持仅对 Spring 的 WebSocket 支持有效。<br/>具体来说,它不能直接使用[JSR-356](https://www.jcp.org/en/jsr/detail?id=356),因为 JSR-356 没有拦截传入 WebSocket 消息的机制。|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
[Index](../index.html)
## HttpSession 设置
第一步是将 Spring Session 与 HttpSession 集成在一起。这些步骤已经在[HttpSession with Redis 指南](./boot-redis.html)中进行了概述。
在继续之前,请确保你已经将 Spring Session 集成到 HttpSession 中。
## Spring 配置
在典型的 Spring WebSocket 应用程序中,你将实现`WebSocketMessageBrokerConfigurer`。例如,配置可能如下所示:
```
@Configuration
@EnableScheduling
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/messages").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/queue/", "/topic/");
registry.setApplicationDestinationPrefixes("/app");
}
}
```
我们可以更新配置以使用 Spring Session 的 WebSocket 支持。下面的示例展示了如何做到这一点:
SRC/main/java/samples/config/websocketconfig.java
```
@Configuration
@EnableScheduling
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractSessionWebSocketMessageBrokerConfigurer<Session> { (1)
@Override
protected void configureStompEndpoints(StompEndpointRegistry registry) { (2)
registry.addEndpoint("/messages").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/queue/", "/topic/");
registry.setApplicationDestinationPrefixes("/app");
}
}
```
要连接 Spring Session 支持,我们只需要更改两件事:
|**1**|而不是实现`WebSocketMessageBrokerConfigurer`,我们扩展`AbstractSessionWebSocketMessageBrokerConfigurer`|
|-----|-----------------------------------------------------------------------------------------------------------------------|
|**2**|我们将`registerStompEndpoints`方法重命名为`configureStompEndpoints`|
`AbstractSessionWebSocketMessageBrokerConfigurer`在幕后做什么?
* `WebSocketConnectHandlerDecoratorFactory`作为`WebSocketHandlerDecoratorFactory`添加到`WebSocketTransportRegistration`。这确保了一个包含`WebSocketSession`的自定义`SessionConnectEvent`被触发。当 Spring Session 结束时,要结束任何仍处于打开状态的 WebSocket 连接,`WebSocketSession`是必需的。
* `SessionRepositoryMessageInterceptor`作为`HandshakeInterceptor`添加到每个`StompWebSocketEndpointRegistration`。这确保将`Session`添加到 WebSocket 属性中,以允许更新上次访问的时间。
* `SessionRepositoryMessageInterceptor`作为`ChannelInterceptor`添加到我们的入站`ChannelRegistration`中。这确保了每次接收入站消息时,都会更新我们 Spring Session 的最后一次访问时间。
* `WebSocketRegistryListener`被创建为 Spring Bean。这确保了我们将所有`Session`ID 映射到相应的 WebSocket 连接。通过维护此映射,我们可以在 Spring Session 结束时关闭所有 WebSocket 连接。
## `websocket`示例应用程序
`websocket`示例应用程序演示了如何在 WebSockets 中使用 Spring Session 。
### 运行`websocket`示例应用程序
你可以通过获取[源代码](https://github.com/spring-projects/spring-session/archive/main.zip)并调用以下命令来运行示例:
```
$ ./gradlew :spring-session-sample-boot-websocket:bootRun
```
| |为了测试会话过期,你可能希望在启动应用程序之前添加以下配置属性,从而将会话过期时间更改为 1 分钟(默认为 30 分钟):<br/><br/>SRC/main/resources/application.properties<br/><br/>```<br/>server.servlet.session.timeout=1m # Session timeout. If a duration suffix is not specified, seconds will be used.<br/>```|
|---|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| |要使示例工作,你必须在 localhost 上[安装 Redis2.8+](https://redis.io/download)并使用默认端口(6379)运行它。<br/>或者,你可以更新`RedisConnectionFactory`以指向 Redis 服务器。<br/>另一个选项是使用[Docker](https://www.docker.com/)在 localhost 上运行 Redis。<br/>有关详细说明,请参见[Docker Redis 存储库](https://hub.docker.com/_/redis/)。|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
现在你应该可以在[http://localhost:8080/](http://localhost:8080/)上访问应用程序了。
### 探索`websocket`示例应用程序
现在你可以尝试使用该应用程序了。使用以下信息进行身份验证:
* **用户 Name ** *罗布*
* **密码** *密码*
现在点击**登录**按钮。你现在应该被验证为用户**罗布**
打开一个隐身窗口并访问[http://localhost:8080/](http://localhost:8080/)
系统会提示你输入登录表单。使用以下信息进行身份验证:
* **用户 Name ** *卢克*
* **密码** *密码*
现在把罗布的话传给卢克。消息应该会出现。
等两分钟,再试着把罗布的信息发送给卢克。你可以看到该消息已不再发送。
| |为什么是两分钟?<br/><br/> Spring Session 在 60 秒内到期,但是来自 Redis 的通知不能保证在 60 秒内发生。<br/>以确保套接字在合理的时间内关闭, Spring Session 在 00 秒时每分钟运行一个后台任务,该任务强制清除任何过期的会话。<br/>这意味着在关闭 WebSocket 连接之前,你最多需要等待两分钟。|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
你现在可以尝试访问[http://localhost:8080/](http://localhost:8080/),提示你再次进行身份验证。这表明会话正确地过期了。
现在重复同样的练习,但不是等待两分钟,而是每 30 秒发送一条来自每个用户的消息。你可以看到消息继续被发送。尝试访问[http://localhost:8080/](http://localhost:8080/),没有提示你再次进行身份验证。这表明会话是保持活力的。
| |只有来自用户的消息才能使会话保持活跃。<br/>这是因为只有来自用户的消息才意味着用户活动。<br/>收到的消息并不意味着活动,因此不会更新会话过期时间。|
|---|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
\ No newline at end of file
此差异已折叠。
# Spring Session 模块
在 Spring session1.x 中, Spring session 的所有`SessionRepository`实现都在`spring-session`工件中可用。虽然方便,但这种方法不能长期持续,因为项目中增加了更多的特性和`SessionRepository`实现。
在 Spring Session2.0 中,将几个模块拆分成独立的模块和托管存储库。 Spring MongoDB 的会话已退役,但后来作为一个单独的模块重新激活。从 Spring Session 2.6 开始,MongoDB 的 Spring Session 被合并回 Spring Session 。
现在,各种存储库和模块的情况如下:
* [`spring-session`Repository](https://github.com/ Spring-projects/ Spring-session)
* 主持 Spring Session 核心、 Spring MongoDB 会话、 Spring Redis 会话、 Spring Session JDBC 和 Spring Session Hazelcast 模块。
* [`spring-session-data-geode`Repository](https://github.com/ Spring-projects/ Spring-session-data-geode)
* 托管 Spring Session 数据 Geode 模块。 Spring Session 数据 Geode 有其自己的用户指南,你可以在[[https://spring.io/projects/spring-session-data-geode#learn](https://spring.io/projects/spring-session-data-geode#learn)站点]上找到它。
最后, Spring Session 还提供了一个 Maven BOM(“物料清单”)模块,以帮助用户处理版本管理问题:
* [`spring-session-bom`Repository](https://github.com/ Spring-projects/ Spring-session-bom)
* 主持 Spring Session BOM 模块
\ No newline at end of file
# 示例和指南(从这里开始)
要开始使用 Spring Session ,最好的起点是我们的示例应用程序。
|来源| Description | Guide |
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|
|[HttpSession with Redis](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-boot-redis)| Demonstrates how to use Spring Session to replace the `HttpSession` with Redis. | [HttpSession with Redis Guide](guides/boot-redis.html) |
|[HttpSession with JDBC](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-boot-jdbc)| Demonstrates how to use Spring Session to replace the `HttpSession` with a relational database store. | [HttpSession with JDBC Guide](guides/boot-jdbc.html) |
|[Hazelcast 的 HttpSession](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-boot-hazelcast)| Demonstrates how to use Spring Session to replace the `HttpSession` with Hazelcast. | |
|[按用户名查找 Name](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-boot-findbyusername)| Demonstrates how to use Spring Session to find sessions by username. | [Find by Username Guide](guides/boot-findbyusername.html) |
|[WebSockets](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-boot-websocket)| Demonstrates how to use Spring Session with WebSockets. | [WebSockets Guide](guides/boot-websocket.html) |
|[WebFlux](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-boot-webflux)| Demonstrates how to use Spring Session to replace the Spring WebFlux’s `WebSession` with Redis. | |
|[带有自定义 cookie 的 WebFlux](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-boot-webflux-custom-cookie)| Demonstrates how to use Spring Session to customize the Session cookie in a WebFlux based application. |[WebFlux with Custom Cookie Guide](guides/boot-webflux-custom-cookie.html)|
|[带有 Redis JSON 序列化的 HttpSession](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-boot-redis-json)| Demonstrates how to use Spring Session to replace the `HttpSession` with Redis using JSON serialization. | |
|[HttpSession with Simple Redis`SessionRepository`](https://github.com/ Spring-projects/ Spring-session/tree/main/ Spring-session-samples/ Spring-session-sample-boot-redis-simple)|Demonstrates how to use Spring Session to replace the `HttpSession` with Redis using `RedisSessionRepository`.| |
|[Spring Session with MongoDB Repositories (servlet-based)](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-boot-mongodb-traditional)| Demonstrates how to back Spring Session with traditional MongoDB repositories. | [Spring Session with MongoDB Repositories](guides/boot-mongo.html) |
|[Spring Session with MongoDB Repositories (reactive)](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-boot-mongodb-reactive)| Demonstrates how to back Spring Session with reactive MongoDB repositories. | [Spring Session with MongoDB Repositories](guides/boot-mongo.html) |
|来源| Description | Guide |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------|--------------------------------------------------------------|
|[HttpSession with Redis](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-javaconfig-redis)| Demonstrates how to use Spring Session to replace the `HttpSession` with Redis. | [HttpSession with Redis Guide](guides/java-redis.html) |
|[HttpSession with JDBC](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-javaconfig-jdbc)|Demonstrates how to use Spring Session to replace the `HttpSession` with a relational database store.| [HttpSession with JDBC Guide](guides/java-jdbc.html) |
|[Hazelcast 的 HttpSession](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-javaconfig-hazelcast)| Demonstrates how to use Spring Session to replace the `HttpSession` with Hazelcast. |[HttpSession with Hazelcast Guide](guides/java-hazelcast.html)|
|[自定义 cookie](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-javaconfig-custom-cookie)| Demonstrates how to use Spring Session and customize the cookie. | [Custom Cookie Guide](guides/java-custom-cookie.html) |
|[Spring Security](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-javaconfig-security)| Demonstrates how to use Spring Session with an existing Spring Security application. | [Spring Security Guide](guides/java-security.html) |
|[REST](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-javaconfig-rest)|Demonstrates how to use Spring Session in a REST application to support authenticating with a header.| [REST Guide](guides/java-rest.html) |
|来源| Description | Guide |
|--------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------|-----------------------------------------------------|
|[HttpSession with Redis](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-xml-redis)| Demonstrates how to use Spring Session to replace the `HttpSession` with a Redis store. |[HttpSession with Redis Guide](guides/xml-redis.html)|
|[HttpSession with JDBC](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-xml-jdbc)|Demonstrates how to use Spring Session to replace the `HttpSession` with a relational database store.| [HttpSession with JDBC Guide](guides/xml-jdbc.html) |
|来源| Description |Guide|
|------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|-----|
|[Hazelcast](https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-misc-hazelcast)|Demonstrates how to use Spring Session with Hazelcast in a Java EE application.| |
\ No newline at end of file
# Spring 安全集成
Spring Session 提供了具有 Spring 安全性的集成。
## Spring 安全 Remember-Me 支持
Spring Session 提供了与[Spring Security’s Remember-me Authentication](https://docs.spring.io/spring-security/site/docs/5.6.2/reference/html5/#servlet-rememberme)的集成。支持:
* 更改会话过期长度
* 确保会话 cookie 在`Integer.MAX_VALUE`处过期。cookie 过期时间被设置为可能的最大值,因为只有在创建会话时才设置 cookie 过期时间。如果将其设置为与会话到期日相同的值,则会话将在用户使用会话时获得更新,但不会更新 cookie 到期日(导致过期时间固定)。
要在 Java 配置中配置具有 Spring 安全性的 Spring Session ,可以使用以下清单作为指导:
```
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ... additional configuration ...
.rememberMe((rememberMe) -> rememberMe
.rememberMeServices(rememberMeServices())
);
}
@Bean
public SpringSessionRememberMeServices rememberMeServices() {
SpringSessionRememberMeServices rememberMeServices =
new SpringSessionRememberMeServices();
// optionally customize
rememberMeServices.setAlwaysRemember(true);
return rememberMeServices;
}
```
基于 XML 的配置类似于以下内容:
```
<security:http>
<!-- ... -->
<security:form-login />
<security:remember-me services-ref="rememberMeServices"/>
</security:http>
<bean id="rememberMeServices"
class="org.springframework.session.security.web.authentication.SpringSessionRememberMeServices"
p:alwaysRemember="true"/>
```
## Spring 安全并发会话控制
Spring Session 提供与 Spring 安全性的集成,以支持其并发的会话控制。这允许限制单个用户可以并发的活动会话的数量,但是,与默认的 Spring 安全支持不同,这也适用于集群环境。这是通过提供 Spring Security 的`SessionRegistry`接口的自定义实现来完成的。
当使用 Spring Security 的 Java Config DSL 时,你可以通过`SessionManagementConfigurer`配置自定义`SessionRegistry`,如下所示:
```
@Configuration
public class SecurityConfiguration<S extends Session> extends WebSecurityConfigurerAdapter {
@Autowired
private FindByIndexNameSessionRepository<S> sessionRepository;
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
// other config goes here...
.sessionManagement((sessionManagement) -> sessionManagement
.maximumSessions(2)
.sessionRegistry(sessionRegistry())
);
// @formatter:on
}
@Bean
public SpringSessionBackedSessionRegistry<S> sessionRegistry() {
return new SpringSessionBackedSessionRegistry<>(this.sessionRepository);
}
}
```
这假定你还配置了 Spring Session ,以提供一个`FindByIndexNameSessionRepository`,返回`Session`实例。
当使用 XML 配置时,它看起来类似于以下清单:
```
<security:http>
<!-- other config goes here... -->
<security:session-management>
<security:concurrency-control max-sessions="2" session-registry-ref="sessionRegistry"/>
</security:session-management>
</security:http>
<bean id="sessionRegistry"
class="org.springframework.session.security.SpringSessionBackedSessionRegistry">
<constructor-arg ref="sessionRepository"/>
</bean>
```
这假定你的 Spring Session `SessionRegistry` Bean 被称为`sessionRegistry`,这是所有`SpringHttpSessionConfiguration`子类使用的名称。
## 限制
Spring session 的 Spring security 的`SessionRegistry`接口的实现不支持`getAllPrincipals`方法,因为无法通过使用 Spring session 来检索此信息。 Spring Security 从不调用此方法,因此这只会影响访问`SessionRegistry`本身的应用程序。
\ No newline at end of file
# 升级到 2.x
有了新的主要版本, Spring Session 团队利用这个机会进行了一些非被动的更改。这些更改的重点是改进和协调 Spring Session 的 API,以及删除不受欢迎的组件。
## 基线更新
Spring Session 2.0 需要 Java8 和 Spring Framework5.0 作为基线,因为其整个代码库现在基于 Java8 源代码。有关升级 Spring 框架的更多信息,请参见[Upgrading to Spring Framework 5.x](https://github.com/spring-projects/spring-framework/wiki/Upgrading-to-Spring-Framework-5.x)
## 替换和移除模块
作为项目拆分模块的一部分,现有的`spring-session`已被`spring-session-core`模块所取代。`spring-session-core`模块只保存公共的一组 API 和组件,而其他模块则包含适当的`SessionRepository`的实现以及与该数据存储相关的功能。这适用于几个现有的模块,这些模块以前是一个简单的依赖聚合器助手模块。通过新的模块设置,以下模块实际进行了实现:
* Spring MongoDB 的会话
* Spring Redis 会议
* Spring Session JDBC
* Spring 会议 Hazelcast
此外,从主项目存储库中删除了以下内容:
* Spring Session 数据 Gemfire
* [`spring-session-data-geode`](https://github.com/ Spring-projects/ Spring-session-data-geode)
## 替换和删除包、类和方法
对包、类和方法进行了以下更改:
* `ExpiringSession`API 已合并到`Session`API 中。
* 已经对`Session`API 进行了增强,以充分利用 Java8。
* `Session`API 已通过`changeSessionId`支持进行了扩展。
* 已经更新了`SessionRepository`API,以更好地与 Spring 数据方法命名约定保持一致。
* 如果没有底层`Session`对象,`AbstractSessionEvent`及其子类将不再可构造。
* `RedisOperationsSessionRepository`使用的 Redis 命名空间现在是完全可配置的,而不是部分可配置的。
* 已更新了 Redis 配置支持,以避免注册 Spring Session 特定的`RedisTemplate` Bean。
* 已更新了 JDBC 配置支持,以避免注册 Spring Session 特定的`JdbcTemplate` Bean。
* 以前不推荐的类和方法已在整个代码库中被删除。
## 支持度下降
作为对`HttpSessionStrategy`的更改及其与来自反应性世界的对应物的对齐的一部分,对在单个浏览器实例中管理多个用户会话的支持已被删除。正在考虑在未来的版本中引入一个新的 API 来取代此功能。
\ No newline at end of file
# WebSession 集成
Spring Session 提供了与 Spring WebFlux 的`WebSession`的透明集成。这意味着你可以使用 Spring Session 支持的实现来切换`WebSession`实现。
## 为什么要进行会话和 WebSession?
我们已经提到, Spring Session 提供了与 Spring WebFlux 的`WebSession`的透明集成,但是我们从中得到了什么好处呢?与`HttpSession`一样, Spring Session 使得在不绑定到特定于应用程序容器的解决方案的情况下支持[群集会话](#websession-redis)变得非常简单。
## 与 Redis 的 WebSession
使用 Spring session with`WebSession`是通过注册一个`WebSessionManager`实现来启用的,该实现由 Spring session 的`ReactiveSessionRepository`支持。 Spring 配置负责创建一个`WebSessionManager`,该实现用 Spring Session 支持的实现替换`WebSession`实现。要做到这一点,请添加以下 Spring 配置:
```
@EnableRedisWebSession (1)
public class SessionConfiguration {
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(); (2)
}
}
```
|**1**|`@EnableRedisWebSession`注释创建了一个名为`webSessionManager`的 Spring Bean。这个 Bean 实现了`WebSessionManager`<br/>这就是负责替换要由 Spring Session 支持的`WebSession`实现的内容。<br/>在这个实例中, Spring Session 是由 Redis 支持的。|
|-----|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|**2**|我们创建一个`RedisConnectionFactory`将 Spring Session 连接到 Redis 服务器。<br/>我们将连接配置为在默认端口(6379)<br/>上连接到 localhost。有关配置 Spring 数据 Redis 的更多信息,请参见[参考文献](https://docs.spring.io/spring-data/data-redis/docs/2.6.2/reference/html/)。|
## WebSession 集成如何工作
与 Servlet API 及其`HttpSession`相比, Spring Session 与 Spring WebFlux 及其`WebSession`集成要容易得多。 Spring WebFlux 提供了`WebSessionStore`API,该 API 提供了用于持久化`WebSession`的策略。
| |本节描述 Spring Session 如何使用`WebSession`提供透明的集成。我们提供这些内容,这样你就可以了解幕后发生了什么。这个功能已经集成了,你不需要自己实现这个逻辑。|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
首先,我们创建一个自定义的`SpringSessionWebSession`,它将委托给 Spring Session 的`Session`。它看起来是这样的:
```
public class SpringSessionWebSession implements WebSession {
enum State {
NEW, STARTED
}
private final S session;
private AtomicReference<State> state = new AtomicReference<>();
SpringSessionWebSession(S session, State state) {
this.session = session;
this.state.set(state);
}
@Override
public void start() {
this.state.compareAndSet(State.NEW, State.STARTED);
}
@Override
public boolean isStarted() {
State value = this.state.get();
return (State.STARTED.equals(value)
|| (State.NEW.equals(value) && !this.session.getAttributes().isEmpty()));
}
@Override
public Mono<Void> changeSessionId() {
return Mono.defer(() -> {
this.session.changeSessionId();
return save();
});
}
// ... other methods delegate to the original Session
}
```
接下来,我们创建一个自定义`WebSessionStore`,它将委托给`ReactiveSessionRepository`,并将`Session`封装到自定义`WebSession`实现中,如下所示:
```
public class SpringSessionWebSessionStore<S extends Session> implements WebSessionStore {
private final ReactiveSessionRepository<S> sessions;
public SpringSessionWebSessionStore(ReactiveSessionRepository<S> reactiveSessionRepository) {
this.sessions = reactiveSessionRepository;
}
// ...
}
```
要被 Spring WebFlux 检测到,此自定义`WebSessionStore`需要在`ApplicationContext`中注册为 Bean 名为`webSessionManager`的 Bean。有关 Spring WebFlux 的更多信息,请参见[Spring Framework Reference Documentation](https://docs.spring.io/spring-framework/docs/5.3.16/reference/html/web-reactive.html)
\ No newline at end of file
# WebSocket 整合
Spring Session 提供了 Spring 的 WebSocket 支持的透明集成。
| |Spring Session 的 WebSocket 支持仅对 Spring 的 WebSocket 支持有效。<br/>具体来说,它不能直接使用[JSR-356](https://www.jcp.org/en/jsr/detail?id=356),因为 JSR-356 没有拦截传入 WebSocket 消息的机制。|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
## 为什么要使用会话和 WebSockets?
那么,当我们使用 WebSockets 时,为什么需要 Spring Session 呢?
考虑一个电子邮件应用程序,它的大部分工作都是通过 HTTP 请求完成的。然而,其中还嵌入了一个聊天应用程序,该应用程序可以在 WebSocket API 上工作。如果用户正在积极地与某人聊天,我们不应该超时`HttpSession`,因为这将是一个非常糟糕的用户体验。然而,这正是[JSR-356](https://java.net/jira/browse/WEBSOCKET_SPEC-175)所做的。
另一个问题是,根据 JSR-356,如果`HttpSession`超时,则任何用`HttpSession`创建的 WebSocket 和经过身份验证的用户都应该被强制关闭。这意味着,如果我们在应用程序中积极地聊天,而不使用 HttpSession,那么我们也会断开与我们的对话的连接。
## WebSocket 用法
[ WebSocket Sample](samples.html#samples)提供了如何将 Spring Session 与 WebSockets 集成的工作示例。你可以遵循下面几个标题中描述的集成的基本步骤,但我们鼓励你在与自己的应用程序集成时遵循详细的 WebSocket 指南。
### `HttpSession`积分
在使用 WebSocket 集成之前,你应该确保首先有[`HttpSession`集成](http-session.html#httpsession)在工作。
#### Spring 配置
在典型的 Spring WebSocket 应用程序中,你将实现`WebSocketMessageBrokerConfigurer`。例如,配置可能如下所示:
```
@Configuration
@EnableScheduling
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/messages").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/queue/", "/topic/");
registry.setApplicationDestinationPrefixes("/app");
}
}
```
我们可以更新配置以使用 Spring Session 的 WebSocket 支持。下面的示例展示了如何做到这一点:
SRC/main/java/samples/config/websocketconfig.java
```
@Configuration
@EnableScheduling
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractSessionWebSocketMessageBrokerConfigurer<Session> { (1)
@Override
protected void configureStompEndpoints(StompEndpointRegistry registry) { (2)
registry.addEndpoint("/messages").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/queue/", "/topic/");
registry.setApplicationDestinationPrefixes("/app");
}
}
```
要连接 Spring Session 支持,我们只需要更改两件事:
|**1**|而不是实现`WebSocketMessageBrokerConfigurer`,我们扩展`AbstractSessionWebSocketMessageBrokerConfigurer`|
|-----|-----------------------------------------------------------------------------------------------------------------------|
|**2**|我们将`registerStompEndpoints`方法重命名为`configureStompEndpoints`|
`AbstractSessionWebSocketMessageBrokerConfigurer`在幕后做什么?
* `WebSocketConnectHandlerDecoratorFactory`作为`WebSocketHandlerDecoratorFactory`添加到`WebSocketTransportRegistration`。这确保了一个包含`WebSocketSession`的自定义`SessionConnectEvent`被触发。当 Spring Session 结束时,要结束任何 WebSocket 仍处于打开状态的连接,`WebSocketSession`是必需的。
* `SessionRepositoryMessageInterceptor`作为`HandshakeInterceptor`添加到每个`StompWebSocketEndpointRegistration`。这确保将`Session`添加到 WebSocket 属性中,以允许更新上次访问的时间。
* `SessionRepositoryMessageInterceptor`作为`ChannelInterceptor`添加到我们的入站`ChannelRegistration`中。这确保了每次接收入站消息时,都会更新 Spring Session 的最后一次访问时间。
* `WebSocketRegistryListener`被创建为 Spring Bean。这确保了我们将所有`Session`ID 映射到相应的 WebSocket 连接。通过维护此映射,我们可以在 Spring Session 结束时关闭所有 WebSocket 连接。
\ No newline at end of file
# Spring 带有自定义 cookie 的会话-WebFlux
本指南描述了如何配置 Spring Session 以在基于 WebFlux 的应用程序中使用自定义 Cookie。该指南假定你已经使用所选的数据存储在项目中设置了 Spring Session 。例如,[HttpSession with Redis ](./boot-redis.html)
| |你可以在[WebFlux 自定义 Cookie 示例应用程序](#webflux-custom-cookie-sample)中找到完整的指南。|
|---|------------------------------------------------------------------------------------------------------------------|
[Index](../index.html)
## Spring 引导配置
一旦设置了 Spring Session ,就可以通过将`WebSessionIdResolver`公开为 Spring Bean 来自定义会话 cookie 的编写方式。 Spring 默认情况下,会话使用`CookieWebSessionIdResolver`。在使用`@EnableRedisHttpSession`之类的配置时,将`WebSessionIdResolver`公开为 Spring Bean 会增强现有的配置。下面的示例展示了如何自定义 Spring Session 的 cookie:
```
@Bean
public WebSessionIdResolver webSessionIdResolver() {
CookieWebSessionIdResolver resolver = new CookieWebSessionIdResolver();
resolver.setCookieName("JSESSIONID"); (1)
resolver.addCookieInitializer((builder) -> builder.path("/")); (2)
resolver.addCookieInitializer((builder) -> builder.sameSite("Strict")); (3)
return resolver;
}
```
|**1**|我们将 cookie 的名称自定义为`JSESSIONID`。|
|-----|--------------------------------------------------------------------------------------------|
|**2**|我们将 cookie 的路径自定义为`/`(而不是上下文根的默认值)。|
|**3**|我们将`SameSite`cookie 指令自定义为`Strict`。|
## `webflux-custom-cookie`示例应用程序
本节介绍如何使用`webflux-custom-cookie`示例应用程序。
### 运行`webflux-custom-cookie`示例应用程序
你可以通过获取[源代码](https://github.com/spring-projects/spring-session/archive/main.zip)并调用以下命令来运行示例:
```
$ ./gradlew :spring-session-sample-boot-webflux-custom-cookie:bootRun
```
| |要使示例工作,你必须在 localhost 上[安装 Redis2.8+](https://redis.io/download)并使用默认端口(6379)运行它。<br/>或者,你可以更新`RedisConnectionFactory`以指向 Redis 服务器。<br/>另一个选项是使用[Docker](https://www.docker.com/)在 localhost 上运行 Redis。详细说明见[Docker Redis 存储库](https://hub.docker.com/_/redis/)。|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
现在你应该可以在[http://localhost:8080/](http://localhost:8080/)上访问应用程序了。
### 探索`webflux-custom-cookie`示例应用程序
现在你可以使用该应用程序了。请在表格中填写以下信息:
* **属性名称:** *用户 Name *
* **属性值:** *罗布*
现在点击**设置属性**按钮。现在你应该可以看到表中显示的值了。
如果查看应用程序的 cookie,可以看到 cookie 已保存到自定义名称`JSESSIONID`
\ No newline at end of file
# 最新更新
还请检查 Spring Session BOM[发行说明](https://github.com/spring-projects/spring-session-bom/wiki#release-notes),以获取新的和值得注意的功能的列表,以及每个版本的升级说明。
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册