用户会话在tomcat上混淆了
我们在IIS7.5之后使用Tomcat 6.29,使用spring,hibernate和struts2框架。 我们现在开始注意到服务器会话正在混淆,特别是在Ajax请求中。
关于这个问题的更多细节
- 用户1请求page1,用户2请求page2。 但是user1获得了page2,而user2获得了server1。
- 会话ID也在变化,但在刷新页面时,会提供正确的页面。
- 当用户数量很多时,问题似乎更频繁发生。
任何指向问题根源的指针都会有所帮助,代码运行正常,用户数量较少,并且没有报告此类实例。
编辑
web.xml中
bm contextConfigLocation classpath:spring/*Context.xml encodingFilter org.springframework.web.filter.CharacterEncodingFilter encoding UTF-8 forceEncoding true struts2 org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter encodingFilter /* struts2 /* org.springframework.web.context.ContextLoaderListener org.apache.struts2.tiles.StrutsTilesListener
在struts.xml
dojo\..*,^struts\..*
其他信息
1)用户通过提交表单登录,登录时我们执行以下操作,
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
EDIT2 INCEPTOR CODE
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; }
两天前我在遗留项目(不是我的)上调试了类似的东西。
原来这是自定义拦截器的错。
检查我在堆栈中可以看到的自定义拦截器,
并确保他们的代码是线程安全的 (避免拦截器上的字段而不是同步所有的东西,只使用局部变量)。
例如,考虑代码:
public abstract class ThreadUnsafeInterceptor extends AbstractInterceptor { private Map session; //