|
对于最新稳定版本,请使用 Spring Session 4.0.2! |
Spring Session 和 Spring Security 与 Hazelcast
此指南描述了在使用Hazelcast作为数据存储时,如何结合Spring Security和Spring Session的用法。 它假设您已经将Spring Security应用于您的应用程序。
| 您可以在Hazelcast Spring Security 样例应用中找到完整的指南。 |
更新依赖项
在使用Spring Session之前,您必须更新您的依赖项。 如果您使用Maven,请添加以下依赖项:
<dependencies>
<!-- ... -->
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast</artifactId>
<version>5.5.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>6.2.16</version>
</dependency>
</dependencies>
Spring 配置
在添加了所需的依赖项后,我们可以创建我们的Spring配置。
Spring 配置负责创建一个servlet过滤器,该过滤器用基于Spring Session 的实现替换掉 HttpSession 实现。
要实现这一点,请添加以下Spring 配置:
@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)
}
}
| 1 | @EnableHazelcastHttpSession 注解创建一个名为 springSessionRepositoryFilter 的 Spring 颗粒(bean),实现 Filter。
该过滤器负责将 HttpSession 实现替换为由 Spring Session 支持的实现。
在这个例子中,Spring Session 由 Hazelcast 支持。 |
| 2 | 要支持按主体名称索引检索会话,需要注册一个合适的ValueExtractor。
Spring Session为此提供了PrincipalNameExtractor。 |
| 3 | 为了高效地序列化MapSession对象,需要注册HazelcastSessionSerializer。如果不设置此配置,Hazelcast 将使用原生Java序列化来序列化会话。 |
| 4 | 我们创建一个HazelcastInstance来将Spring Session与Hazelcast连接起来。
默认情况下,应用程序启动并连接到嵌入式Hazelcast实例。
有关配置Hazelcast的更多信息,请参阅参考文档。 |
如果希望使用HazelcastSessionSerializer,则需要在所有Hazelcast集群成员启动之前进行配置。
在Hazelcast集群中,所有成员都应使用相同的会话序列化方法。另外,如果使用了Hazelcast客户端/服务器架构,则成员和客户端都必须使用相同的序列化方法。可以通过ClientConfig注册序列化器,并使用与成员相同的SerializerConfiguration。 |
Servlet 容器初始化
我们的springSessionRepositoryFilter的 Spring bean,该bean实现了Filter。
springSessionRepositoryFilter bean负责用一个由 Spring Session 支撑的自定义实现来替换HttpSession。
为了使我们的Filter发挥魔力,Spring 需要加载我们的SessionConfig类。
由于我们已经通过使用SecurityInitializer类来加载应用程序的 Spring 配置,因此我们可以将SessionConfig类添加到其中。
以下列表显示了如何实现这一点:
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
public SecurityInitializer() {
super(SecurityConfig.class, SessionConfig.class);
}
}
最后,我们需要确保我们的Servlet容器(即Tomcat)为每个请求使用我们的springSessionRepositoryFilter。
这非常重要的是,Spring Session的springSessionRepositoryFilter必须在Spring Security的springSecurityFilterChain之前被调用。
这样做可以确保Spring Security使用的HttpSession是由Spring Session支持的。
幸运的是,Spring Session提供了一个名为AbstractHttpSessionApplicationInitializer的工具类,使得这一操作变得简单。
以下示例展示了如何实现这一点:
public class Initializer extends AbstractHttpSessionApplicationInitializer {
}
我们的类名(Initializer)无关紧要。重要的是我们继承了AbstractHttpSessionApplicationInitializer。 |
通过扩展AbstractHttpSessionApplicationInitializer,我们确保名为springSessionRepositoryFilter的Spring bean在每次请求中都会被注册到我们的Servlet容器中,在Spring Security的springSecurityFilterChain之前。
Hazelcast Spring Security示例应用
此部分描述了如何与Hazelcast Spring Security示例应用程序进行交互。
运行示例应用程序
您可以运行示例程序,通过获取源代码并执行以下命令来实现:
$ ./gradlew :spring-session-sample-javaconfig-hazelcast:tomcatRun
| 默认情况下,Hazelcast会在应用程序中以嵌入模式运行。 但是,如果您想要连接到一个独立实例,可以通过遵循参考文档中的说明进行配置。 |
您应该能够通过以下地址访问应用:localhost:8080/
探索安全示例应用程序
现在您可以尝试使用应用程序。 要进行操作,请输入以下内容登录:
-
用户名 user
-
密码 密码
现在点击 登录 按钮。
你应该会看到一个消息,表明你已经使用之前输入的用户信息进行了登录。
用户的个人信息存储在 Hazelcast 而不是 Tomcat 的 HttpSession 实现中。
它是如何工作的?
我们不再使用Tomcat的HttpSession,而是将值持久化在Hazelcast中。
Spring Session用一个由Hazelcast支持的实现替换了HttpSession。
当Spring Security的SecurityContextPersistenceFilter将SecurityContext保存到HttpSession时,它会被持久化到Hazelcast中。
与数据存储交互
使用控制台
例如,在连接到您的Hazelcast节点后,可以通过管理中心控制台移除会话,请运行以下命令:
default> ns spring:session:sessions spring:session:sessions> m.clear
| The Hazelcast 文档有针对控制台的说明。控制台。 |
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
现在访问应用,在localhost:8080/,观察我们不再进行身份验证。
使用 REST API
如文档中描述的其他客户端部分所述,Hazelcast 节点提供了 REST API 。
例如,您可以按照以下方式删除一个单独的密钥(请确保将7e8383a4-082c-4ffe-a4bc-c40fd3363c5e替换为您SESSION cookie的值):
$ curl -v -X DELETE http://localhost:xxxxx/hazelcast/rest/maps/spring:session:sessions/7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
Hazelcast 节点的端口号在启动时会打印到控制台。请将 xxxxx 替换为端口号。 |
现在您已注销,无法再通过此会话进行身份验证。