我有SpringBoot 2.0.0.M7
项目,我WebSession
使用Redis
(org.springframework.session:spring-session-data-redis:2.0.0.RELEASE
)。
我有一个WebFlux路由,应该使用eBay会话ID重定向到eBay。每次用户访问该路由时,我都需要从eBay API请求不同的会话ID并将其包含在重定向URL中。之后,eBay会将用户重定向回我的应用程序,我需要该会话ID来请求令牌。
在测试期间,我发现当浏览器仍然具有包含现有会话ID的cookie时,会话属性的值(在我的情况下,它是ebay_session_id
)不能用新值替换。在我再次请求ebay_session_id
的路线中,我得到了旧的价值,而不是新的价值。
存储SessionID的代码如下:
return ebayApiReactiveWrapper
.getSessionId(apiContext)
.flatMap(sessionId ->
request
.session()
.map(webSession -> {
webSession
.getAttributes()
.put("ebay_session_id", sessionId);
return sessionId;
})
)
.flatMap(sessionId -> {
final UriBuilder uriBuilder = uriBuilderFactory.uriString(
ebayApiSettings.getSignInUrl()
);
uriBuilder.queryParam("runame", ebaySettings.getRuName());
uriBuilder.queryParam("SessID", sessionId);
return ServerResponse.temporaryRedirect(redirectUri).build();
});
我尝试在webSession.save()
方法之后添加put
,但它没有帮助。
我做错了什么?提前谢谢!
更新
有关Redis中会话数据发生情况的一些新细节。创建会话时(空Redis),数据看起来像这样:
127.0.0.1:6379> hkeys "spring:session:sessions:cbbf8000-6ce8-4238-a427-9aab37d2702b"
1) "lastAccessedTime"
2) "maxInactiveInterval"
3) "creationTime"
4) "sessionAttr:ebay_session_id"
当我第二次访问相同路线时(会话cookie仍然存在且会话数据仍在Redis中),数据正在发生变化:
127.0.0.1:6379> hkeys "spring:session:sessions:cbbf8000-6ce8-4238-a427-9aab37d2702b"
1) "sessionAttr:ebay_session_id"
通过,sessionAttr:ebay_session_id
仍然包含第一个请求的值。
最糟糕的是,当另一条路由尝试获取会话数据时,此类结构会导致NullPointerException
。看起来它期待其他3个字段被呈现并且在不是这种情况时失败。
答案 0 :(得分:0)
看起来没有多少人遇到过这样的问题。我找到了解决问题的解决方案。
如果未更改会话的属性集,我看到该会话不会更新。所以每次我需要更新会话值时,我都会添加一个新属性。问题代码中的第一个flatMap
按以下方式更改:
.flatMap(sessionId ->
request
.session()
.map(webSession -> {
// we need to check if session already started before applying "hack"
if (webSession.isStarted()) {
// "hack"
final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yMdkmsn");
webSession
.getAttributes()
.put(LocalDateTime.now().format(dateTimeFormatter),"1");
}
webSession
.getAttributes()
.put("ebay_session_id", sessionId);
return sessionId;
})
)
添加新属性后,会话被视为已更改,并将以redis更新。
答案 1 :(得分:0)
我遇到了这个问题并使用了几乎相同的hack,只是更新了原始类型的会话属性。
例如:
webSession.getAttributes().put("userContext", userContext);
webSession.getAttributes().put("lastContextUpdateTime", System.currentTimeMillis());
这可以避免为每个会话更新添加新属性,但也会在Redis中触发可变对象更新。