【问题标题】:What is the proper way to update attribute value in started Spring WebSession?在启动的 Spring WebSession 中更新属性值的正确方法是什么?
【发布时间】:2018-02-15 21:20:47
【问题描述】:

我有 SpringBoot 2.0.0.M7 项目,我正在使用 WebSessionRedis (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();
        });

我尝试在put 方法之后添加webSession.save(),但没有帮助。

我做错了什么?提前谢谢!

更新

关于 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 个字段,但如果不是这样,则会失败。

【问题讨论】:

    标签: spring spring-session spring-webflux


    【解决方案1】:

    看起来没有多少人遇到过这样的问题。我找到了解决它的方法。

    我看到如果不更改会话的属性集,会话将不会更新。因此,每次需要更新会话值时,我都会添加一个新属性。我的问题代码中的第一个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 中更新。

    【讨论】:

      【解决方案2】:

      我遇到了这个问题并使用了几乎相同的技巧,但只是通过更新原始类型会话属性。

      例如:

      webSession.getAttributes().put("userContext", userContext);
      
      webSession.getAttributes().put("lastContextUpdateTime", System.currentTimeMillis());
      

      这避免了为每次会话更新添加新属性,但也会触发 Redis 中的可变对象更新。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-04-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-17
        • 2021-04-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多