用户会话在tomcat上混淆了 [英] User session getting mixed up on tomcat

查看:95
本文介绍了用户会话在tomcat上混淆了的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们在IIS7.5后面使用Tomcat 6.29,使用spring,hibernate和struts2框架。我们现在开始注意到服务器会话正在混淆,特别是在Ajax请求中。

We are using Tomcat 6.29 behind IIS7.5, with spring, hibernate and struts2 framework. We are now beginning to notice that the server sessions are getting mixed up especially in Ajax request.

关于问题的更多细节


  • 用户1请求page1,用户2请求第2页。但是user1获得了第2页的服务,而user2获得了服务器page1。

  • 会话ID也在变化,但在刷新页面时,会提供正确的页面。

  • 当用户数量很高时,问题似乎更频繁发生。

任何指向问题根源的指针会有所帮助,代码运行正常,用户数量较少,并且没有报告此类实例。

Any pointers to the origin of the problem would help, the code runs fine with lesser number of users and no such instance is reported.

编辑

web.xml

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">

<display-name>bm</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/*Context.xml</param-value>
</context-param>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
  <param-name>encoding</param-name>
  <param-value>UTF-8</param-value>
</init-param>
<init-param>
  <param-name>forceEncoding</param-name>
  <param-value>true</param-value>
</init-param>
</filter>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
  <listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class>
</listener>

struts.xml

<result-types>
        <result-type name="jasper" class="org.apache.struts2.views.jasperreports.JasperReportsResult"/>
        <result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult" />
    </result-types> 

    <interceptors>

        <interceptor name="sessionLoggin" class="com.inrev.bm.interceptor.IRLoggingInterceptor" />
        <interceptor name="appAccess" class="appAccessInterceptor" />

        <interceptor-stack name="newStack">
            <interceptor-ref name="exception"/>
            <interceptor-ref name="alias"/>
            <interceptor-ref name="servletConfig"/>
            <interceptor-ref name="i18n"/>
            <interceptor-ref name="prepare"/>
            <interceptor-ref name="chain"/>
            <interceptor-ref name="debugging"/>
            <interceptor-ref name="scopedModelDriven"/>
            <interceptor-ref name="modelDriven"/>
            <interceptor-ref name="fileUpload"/>
            <interceptor-ref name="checkbox"/>
            <interceptor-ref name="multiselect"/>
            <interceptor-ref name="staticParams"/>
            <interceptor-ref name="params">
                <param name="excludeParams"> dojo\..*,^struts\..*</param>
            </interceptor-ref>
            <interceptor-ref name="actionMappingParams"/>
            <interceptor-ref name="sessionLoggin"/>
            <interceptor-ref name="appAccess"/>
        </interceptor-stack>
    </interceptors>

 <default-interceptor-ref name="newStack"/>

其他信息

1)用户通过提交表单登录,登录时我们执行以下操作:

1) Users are login in by submitting a form, on login we perform the following,

public class xxxAction extends ActionSupport implements SessionAware  
{
    public String execute()
{
      session.clear();
      if (session instanceof org.apache.struts2.dispatcher.SessionMap) 
      {
    try 
    {
       ((org.apache.struts2.dispatcher.SessionMap) session).invalidate();
    }
    catch (IllegalStateException e) {
      log.error("Session Invalidate Failed ", e);
        }

        //Authorization code happens here
        session.put("orgs", orgs);
    session.put("currentOrg", org);
    session.put("permission", adminDAO.getRolePermission(orgs.get(0).getRoleId()));
    session.put("simplyApp", simplyApp);
    session.put("user", user);

       return "login"
    }
}

2)正在使用的是Windows 2008 RC2

2) Os being used is windows 2008 RC2

EDIT2 INCEPTOR CODE

EDIT2 INCEPTOR CODE

INTERCEPTOR 1

INTERCEPTOR 1

public String intercept(ActionInvocation invocation) throws Exception 
{
    String result = null;

    String className = invocation.getAction().getClass().getName();
    Map session = invocation.getInvocationContext().getSession();

    IRUser user = (IRUser) session.get("user");
    IROrgname org = (IROrgname)session.get("currentOrg");
    IRAppDetails simplyApp = (IRAppDetails)session.get("simplyApp");
    String sessionId = (String)session.get("sessionId");
    boolean switchUser =session.get("switchUser")!=null ? (Boolean)session.get("switchUser") : false;

    if(className.indexOf("IRLoginAction")!=-1 || className.indexOf("IRContactUsAction")!=-1 
            || className.indexOf("IRIPNAction")!=-1 || className.indexOf("IRPaymentAction")!=-1 
            || className.indexOf("IRServiceAction")!=-1 || className.indexOf("IRAppBossAction") !=-1) 
    {
        result= invocation.invoke();
        session.put("PREV_CLASS_NAME", className);
    }
    else if(!(className.indexOf("IRLoginAction")!=-1) && (user !=null && org!=null))
    {
        if(!IRSessionManager.getInstance().compareSession(user.getUserId(), sessionId) && !switchUser)
        {
            session.clear();
            if (session instanceof org.apache.struts2.dispatcher.SessionMap) 
            {
                try 
                {
                    ((org.apache.struts2.dispatcher.SessionMap) session).invalidate();
                }
                catch (IllegalStateException e) 
                {
                    log.error("Session Invalidate Failed ", e);
                }
            }
            result = "sessionDuplicated";

        }
        else
        {
            result= invocation.invoke();
            session.put("PREV_CLASS_NAME", className);
        }
    }
    else if(className.indexOf("widgets") !=-1)
    {
        result= invocation.invoke();
    }
    else if(className.indexOf("ActionSupport") !=-1)
    {
        result= invocation.invoke();
    }
    else if (!(className.indexOf("IRLoginAction")!=-1) && (user ==null || org==null || simplyApp==null))
    {
        result = "sessionExpired";
    }

    return result;
}

INTERCEPTOR 2

    public String intercept(ActionInvocation invocation) throws Exception 
{
    String result = null;

    HttpServletRequest request = ServletActionContext.getRequest();


    String className = invocation.getAction().getClass().getName();

    try
    {
        Map session = invocation.getInvocationContext().getSession();

        IRUser user = (IRUser) session.get("user");
        IROrgname org = (IROrgname)session.get("currentOrg");
        IRAppDetails application = (IRAppDetails)session.get("simplyApp");

        if(( user!= null && user.getAppType()!=0) &&  !(className.indexOf("IRLoginAction")!=-1))
        {
            if(hasAccess(user.getAppType(), className))
            {
                result= invocation.invoke();
            }
            else
            {
                result = "checkURL";
            }
        }
        else
        {
            result= invocation.invoke();
        }
    }
    catch (Exception e) 
    {
        e.printStackTrace();
    }

    return result;
}


推荐答案



<我两天前在一个遗留项目(不是我的)上调试了类似的东西。

I've debugged something similar two days ago on a legacy project (not mine).

原来这是自定义Interceptors的错。

It turned out it was custom Interceptors's fault.

检查我在堆栈中可以看到的自定义拦截器,

Check the custom Interceptors i can see in your stack,

        <interceptor-ref name="sessionLoggin"/>
        <interceptor-ref name="appAccess"/>

并确保其代码线程安全(避免拦截器上的字段而不是同步所有东西,只使用局部变量)。

and ensure that their code is Thread Safe (avoid fields on interceptors instead of synchronize all your stuff, use only local variables).

例如,考虑代码:

public abstract class ThreadUnsafeInterceptor extends AbstractInterceptor {

    private Map<String, Object> session; // <!-- Thread Unsafe

    public final String intercept(ActionInvocation invocation) throws Exception {
        session = invocation.getInvocationContext().getSession();       
        /* Do stuff */

        System.out.println(session.get("myObject"));        

        return invocation.invoke();
    }
}

这样,当User1输入方法时,它会设置共享会话对象及其会话;
如果User2在User1尚未完成时输入方法,User2将立即覆盖 session 对象及其会话,User1将引用User2会话而不是其拥有。

This way, when User1 enters the method, it sets the shared session object with its session; if User2 enters the method while User1 has not yet finished, User2 will immediately override the session object with its session, and User1 will refer to User2 session instead of its own.

为了使其线程安全,它应如下所示:

To make it thread safe it should be like follows:

public abstract class ThreadSafeInterceptor extends AbstractInterceptor {

    public final String intercept(ActionInvocation invocation) throws Exception {

        Map<String, Object> session; // <!-- Thread Safe

        session = invocation.getInvocationContext().getSession();

        /* Do stuff */

        System.out.println(session.get("myObject"));        

        return invocation.invoke();
    }
}






编辑:


您的拦截器存在一些问题:

Your interceptors present some problems:

1)请求不得以这种方式访问​​(如上所述) 此处):

1) Request must not be accessed this way (as described here):

HttpServletRequest request = ServletActionContext.getRequest();

从Struts2拦截器中访问请求的正确方法是:

the right way to access the request from within an Struts2 Interceptor is:

// Constants are from StrutsStatics interface
HttpServletRequest request = (HttpServletRequest) context.get(HTTP_REQUEST); 

2)如果你不想返回 invocation.invoke( ); 立即请注意,将其分配给结果字符串将触发流,以及 invoke()将在Action执行后执行,如此处所述

2) If you don't want to return the invocation.invoke(); immediately, please note that assigning that to the result String will fire the "flow", and the lines after the invoke() will be executed AFTER the Action execution, as described here:

public String intercept(ActionInvocation invocation) throws Exception {

    String className = invocation.getAction().getClass().getName();
    long startTime = System.currentTimeMillis();
    System.out.println("Before calling action: " + className);

    String result = invocation.invoke();

    long endTime = System.currentTimeMillis();
    System.out.println("After calling action: " + className
            + " Time taken: " + (endTime - startTime) + " ms");

    return result;
}

这篇关于用户会话在tomcat上混淆了的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆