我的 Spring BFF 几乎可以工作了。
显式注销
当我明确注销时,将调用以下函数,因此会话将从以下位置删除:(i) 命名空间 > 会话,(ii) 命名空间 > 会话 > 过期,(iii) 命名空间 > 会话 > 会话 id > idx,(iv)和命名空间 > 会话 > 过期(排序集)
这叫这个和这个:
这叫这个和这个:
两者最终都称之为:
这里调用了4个删除方法
还调用以下命令来执行 RP 发起的注销(也结束与 Auth0 授权服务器存在的会话)
BFF 会话自然过期
但是,当 BFF 会话达到其自然到期时间时,我该如何执行上述操作。 当这种情况发生时Redis仍然留下以下内容
此外,Auth0 会话永远不会注销(因此,如果该人通过 Spring BFF 再次登录,并且 Auth0 会话仍然有效,并且它将静默登录而不显示 Auth0 登录页面)
我认为Spring Session在会话过期时不会自动通知应用程序。因此,我们需要一种方法来检测 Redis 中的会话何时过期。我们可以通过设置一个计划任务来实现这一点,该任务定期检查过期的会话并相应地处理它们,类似于 SessionEvicter 清理会话的方式。一旦检测到会话过期,我们就可以
此外,Spring Session 没有内置支持在会话自然过期时执行自定义逻辑,但我们可以通过订阅 Redis 键过期事件来监听会话删除。我们可以配置 Redis 来发布密钥过期事件,并在 Spring 应用程序中设置监听器来处理这些事件。
示例代码
@Configuration
public class RedisKeyExpirationListenerConfig {
@Bean
RedisMessageListenerContainer keyExpirationListenerContainer(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
@Bean
KeyExpirationEventMessageListener redisKeyExpirationListener(
RedisMessageListenerContainer listenerContainer) {
return new KeyExpirationEventMessageListener(listenerContainer);
}
}
@Component
public class KeyExpirationEventMessageListener extends KeyspaceEventMessageListener {
public KeyExpirationEventMessageListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
@Override
public void onMessage(Message message, byte[] pattern) {
String expiredKey = message.toString();
// Check if the key matches session keys
if (expiredKey.startsWith("spring:session:")) {
// Perform custom cleanup and logout from Auth0
handleSessionExpiration(expiredKey);
}
}
private void handleSessionExpiration(String sessionId) {
// 1. Remove session-related data from Redis
// 2. Trigger RP-Initiated Logout from Auth0
}
}
最后注销 Auth0 会话,在处理过期会话时向 Auth0 注销端点发送请求
private fun performAuth0Logout(sessionId: String) {
val logoutUrl = "https://YOUR_AUTH0_DOMAIN/v2/logout"
val request = WebClient.create(logoutUrl)
.get()
.uri { uriBuilder ->
uriBuilder.queryParam("client_id", "YOUR_CLIENT_ID")
.queryParam("returnTo", "YOUR_LOGOUT_REDIRECT_URI")
.build()
}
.retrieve()
.bodyToMono(Void::class.java)
request.subscribe(
{ logger.info("Auth0 session for session $sessionId successfully logged out.") },
{ error -> logger.error("Error logging out from Auth0: ${error.message}") }
)
}