-1

我有类似的问题...当并发登录问题发生时,我想重定向到“/concurrent.htm?concurrencyError=true”。

配置如下:

 <beans:bean id="concurrencyFilter"
  class="org.springframework.security.web.session.ConcurrentSessionFilter" >
  <beans:property name="sessionRegistry" ref="sessionRegistry" />
  <beans:property name="expiredUrl" value="/concurrent.htm?concurrencyError=true" />
  <beans:property name="redirectStrategy" ref="customForwardStrategy" />

但问题是它被重定向到“login.htm”,而与“expiredUrl”中定义的值无关。我调试并发现根本原因是,首先我的转发到 concurrent.htm 的请求发生在 concurrencySessionFilter 中,但是在该过滤器链序列继续之后,由于会话在身份验证链中将为空,它被重定向到“loginFormUrl”,即, login.htm(此特定请求出现在 ExceptionTranslationFilter 中的 handleException() 方法 -> 在下面显示的行处 @sendStartAuthentication

else if (exception instanceof AccessDeniedException) {
        if   (authenticationTrustResolver.isAnonymous(SecurityContextHolder.getContext().getAuthentication())) {
            if (logger.isDebugEnabled()) {
                logger.debug("Access is denied (user is anonymous); redirecting to authentication entry point",
                        exception);
            }

            sendStartAuthentication(request, response, chain, new InsufficientAuthenticationException(
                    "Full authentication is required to access this resource"));)

所以我之前对“concurrent.htm”的请求被下一个请求“login.htm”覆盖,并且我被重定向到登录页面而不是 concurrency.jsp 页面。

一旦并发过滤器中发生并发错误,我是否需要添加任何配置以停止进一步过滤,以便我可以重定向/转发到我配置的页面???

4

1 回答 1

1

我找到了问题的根本原因。

根本原因:

问题不在于 spring 3.0.5 版本或某些配置。这一切都归功于我的一个 js 文件中的一小段代码:

/* session timeout handling */
Ext.Ajax.on("requestcomplete", function(conn, response, options){
    //We can do nicer things here, like showing a login window and let
    //the user login on the same screen. But now we simply redirects the
    //user to the login page.
 if(response.responseText.indexOf("<html>") > 0){
    window.location = mFino.BASE_URL + "login.htm";
 }
});

这里要做的是:由于我们的网站完全是使用 extjs 构建的,我们确实发送了 ajax 请求,所以如果我们发送一个 ajax 请求,让我们说“fix.htm”(一旦用户一次登录多个系统),序列过滤器被调用,当 ConcurrentSessionFilter 被调用时,重定向发生在“concurrent.jsp”并且过滤被终止(当然,正如我所说的,当一次发送多个请求时,即使在并发过滤器中发生重定向并且过滤器被终止,另一个请求将通过定义的过滤器,而不管第一个请求是否被重定向 - 然后在异常过滤器中引发 AccessDeniedException 并重定向到 login.htm 并行发生 - 但这不是根本原因,因为即使只有 1 ajax 请求已发送)所以最后是并发的。jsp 内容作为对 ajax 请求的响应发送。

内容(即 response.responseText 中的

   Ext.Ajax.on("requestcomplete", function(conn, response, options)) 

将是一个类似于...的html页面

"<html>
    <head>
        <title>Adminapplication- concurrency issue page</title>......."

由于满足条件,用户将根据代码重定向到登录页面:

 if(response.responseText.indexOf("<html>") > 0){
     window.location = mFino.BASE_URL + "login.htm";
 }

保持此条件的目的是:通常,ajax 请求的响应将是 JSON 或 XML 类型的示例,例如:

 {success:true, message:'User name is xxx'}

所以如果有的话,如果他们得到除了这种类型的响应(比如 html 响应),可以说是由于会话超时,他们只是重定向到login.htm

这是影响我重定向到“ concurrent.htm ”的根本原因。

我为此想出的解决方案是:

将concurrenyHandler中的逻辑更改为发送 json 响应,而不是重定向到并发 jsp,这将生成 html 响应 ...如下:

前:

@RequestMapping("/concurrent.htm")

public View concurrenyHandler(HttpServletRequest request, HttpServletResponse response){
        return new ModelAndView("concurrent");
    }

后:

@RequestMapping("/concurrent.htm")

public View concurrenyHandler(HttpServletRequest request, HttpServletResponse response){
        HashMap<String,Object> map = new HashMap<String, Object>();
        map.put("success", true);
        map.put("Error", MessageText._("Session Expired"));
        return new JSONView(map); //JSONView is our custom class which implements org.springframework.web.servlet.View and renders json object as string just like ..."out.write(this.jsonObject.toString());"
     }

在 js 文件中,将“on requestcomplete ”功能更改如下,

/* session timeout handling */
Ext.Ajax.on("requestcomplete", function(conn, response, options){
    //We can do nicer things here, like showing a login window and let
    //the user login on the same screen. But now we simply redirects the
    //user to the login page.
    /*if(response.responseText.indexOf("<html>") > 0){
    window.location = mFino.BASE_URL + "login.htm";
    }*/
 if(response.responseText.indexOf("Session Expired") > 0){
    window.location = mFino.BASE_URL + "login.htm?sessionExpired=true";
 }
});

在 login.jsp 中,我将检查 sessionExpired=true 条件并使用以下消息发出警报,

if('<%=request.getParameter("sessionExpired")%>'=='true'){
    alert("The session is expired due to timeout or because the same user logged in on another system");
}

更改弹簧设置如下:

 .......<custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
    <custom-filter ref="authenticationProcessingFilter" before="FORM_LOGIN_FILTER" />        
    <custom-filter ref="customSessionManagementFilter" after="SESSION_MANAGEMENT_FILTER" />


    <session-management session-authentication-strategy-ref="sas" invalid-session-url="/concurrent.htm"/>
</http>

<beans:bean id="authenticationProcessingFilter" class="com.mfino.uicore.security.AuthProcessingFilter">
    <beans:property name="authenticationManager" ref="authenticationManager" />
    <beans:property name="sessionAuthenticationStrategy" ref="sas" />
</beans:bean>

 <beans:bean id="customSessionManagementFilter" class="com.mfino.uicore.security.CustomSessionManagementFilter">
</beans:bean>


<beans:bean id="concurrencyFilter"
    class="org.springframework.security.web.session.ConcurrentSessionFilter" >
    <beans:property name="sessionRegistry" ref="sessionRegistry" />
    <beans:property name="expiredUrl" value="/concurrent.htm" />
</beans:bean>..........

现在,当根据需要发生并发异常时,我可以在登录页面中显示带有消息的警报[以前我担心的主要问题是我无法发送像'sessionExpired = true'这样的请求参数来检查登录页面中的条件并发出警报,因为我不断地被重定向到 login.htm(没有任何此类请求参数),而不管 Spring 处理程序完成的重定向]。

感谢@LukeTaylor 指导我!!!!

于 2012-09-27T13:02:01.973 回答