Spring webflow externalRedirect重启相同的流程

时间:2012-10-30 18:09:26

标签: java spring-mvc spring-webflow cas

我正在使用CAS,刚刚从3.4.8更新到3.5.1。已经有一千个变化,我认为我已经处理了大多数。但是,完成后的externalRedirect似乎以某种方式被破坏了。它只是循环回到login-webflow的开始。怎么会发生这种情况?

这是达到的最终状态:

  <!-- The "redirect" end state allows CAS to properly end the workflow while 
    still redirecting the user back to the service required. -->
  <end-state id="redirectView"
    view="externalRedirect:${requestScope.response.url}" />

我知道它已经达到了,因为我在这个方法中设置了一个断点(org.springframework.webflow.action.ExternalRedirectAction):

protected Event doExecute(RequestContext context) throws Exception {
    String resourceUri = (String) this.resourceUri.getValue(context);
    context.getExternalContext().requestExternalRedirect(resourceUri);
    return success();
}

如果我在此方法返回之前检查resourceUri的值,我会看到uri应该将此请求重定向到:

http://mycompany.com:8080/c/portal/login?redirect=%2Fweb%2Fguest%2Fhome&ticket=ST-4-jVOtEEZcy9bXdb4xiV3l-cas

但是,如果我只是从该断点运行,而不是重定向到该页面,则相同的login-webflow重新开始。这里发生了什么?我应该在哪里看?有没有调试的提示?

---------------更新---------------

因此,在对代码进行0次修改后,只需添加一些额外的断点,它现在可以按预期工作。我不知道这里发生了什么,但我终于找到了实际重定向发生的地方。对于那些感兴趣的人,重定向发生在:

org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handleFlowExecutionResult(
        FlowExecutionResult result, ServletExternalContext context,
        HttpServletRequest request, HttpServletResponse response, FlowHandler handler)

2 个答案:

答案 0 :(得分:2)

看起来这个帖子已经休眠了一段时间,但是我想为将来可能出现的任何人提供一些信息。以下解释源自我对CAS 4.0.1的经验。如果这不适用于旧版本,我会感到震惊......

首先要检查的是您的身份验证过程是否相对缓慢。例如,如果您是通过VPN链接访问身份验证数据库的开发人员。或者,如果您的身份验证查询(和故障单存储)只是相对较慢......

如果这适用于您,我在CAS中发现了一个问题,它以一种奇怪的方式与Tomcat交互,表现出上述行为。

CAS中的问题出现在名为TerminateWebSessionListener的Web流侦听器中。它似乎是在流程完成后通过快速到期会话来保持内存使用率较低的尝试。问题是,它实施起来非常天真。它只是抓取会话并在其上设置2秒的“最大非活动时间间隔”(默认情况下 - 您可以使用timeToDieInSeconds中的TerminateWebSessionListener的cas-servlet.xml属性更改它。)

与Tomcat的交互是这样的:Tomcat在请求中第一次访问会话时标记会话的“上次访问”时间每次检索会话时,会根据当前时间检查上次访问时间,以确定是否已经过了无效时间间隔。

所以发生的事情是TerminateWebSessionListener期望HttpSession.setMaxInactiveInterval(2)导致会话在那之后无效2秒它真正告诉Tomcat要做的是使会话无效2 在当前请求中第一次访问之后的几秒钟。如果您的身份验证/登录请求发生的时间超过2秒,那么BOOM! - 您的会话在下次有人要求时会失效同样的要求。不幸的是,这个问题发生在Spring WebFlow本身。所以你在这里遇到了竞争条件。

我将更多地考虑这个问题,并希望向CAS团队提出修复建议。在此期间,您可以在cas-servlet.xml中禁用TerminateWebSessionListener,也可以将其timeToDieInSeconds的值提高到预期比完成身份验证请求所需的时间更长的值。也许30秒?这样做似乎是合理的。它似乎不是一种安全措施,只是一种节省内存的措施。

代码参考:

  • CAS 4.0.1
    • TerminateWebSessionListener.java:33(sessionEnded()
      • CAS在此处设置会话失效间隔。
  • Tomcat 7.0.55:
    • Request.java:338( session实例变量。)
      • Tomcat将会话存储在请求的持续时间内。
    • Request.java:2899({ doGetSession()
      • 会话提前返回,如果已经缓存在请求上,则返回access()
    • Request.java:2921({ doGetSession()
      • 在请求中首次访问时,会话被查找,access()被调用,并在请求中缓存。

(注意:StandardSession.access()只是使用{em>上次访问时间System.currentTimeMillis()标记会话。)

答案 1 :(得分:0)

我发现了一些有用的东西。可能适用于您的具体问题,也可能不适用。但是如果将此流称为子流,则将忽略结束状态的view参数。

但是,如果您只是正常调用此流程,它将执行重定向。您可以采取的措施是使用view-state代替end-state。但这会让你保持流动和父流动开放。