dwr 出现session error错误的处理

来源:互联网 发布:qt creator windows 编辑:程序博客网 时间:2024/05/22 16:19

在使用dwr的时候遇到了session error 错误解决方法,就是在web.xml 中配置如下:
<!-- DWR servlet,生产环境应该Debug为false -->
<servlet>
   <servlet-name>dwr-invoker</servlet-name>
   <servlet-class>
    org.directwebremoting.servlet.DwrServlet
   </servlet-class>
   <init-param>
    <param-name>debug</param-name>
    <param-value>true</param-value>
   </init-param>
   <init-param>
    <param-name>logLevel</param-name>
    <param-value>warn</param-value>
   </init-param>
   <init-param>
    <param-name>crossDomainSessionSecurity</param-name>
    <param-value>false</param-value>
   </init-param>
   <load-on-startup>1</load-on-startup>
</servlet>
当中的那个  
<init-param>
    <param-name>crossDomainSessionSecurity</param-name>
    <param-value>false</param-value>
   </init-param>

是为处理这个问题而加入的,经验证的确好用。

这是同源策略的问题,为了WEB环境的安全,在WEB脚本语言中不允许读取不同源的数据,同源包括相同协议,相同域名和相同端口三个条件,可以看这里:
http://www.ynutx.net/raindesign/blog/archive/209.html
而Ajax的异步处理方式跳过了这个限制,为了安全限制,它设置为sameDomainAccess,
这里有些突破这种限制的方式:http://tech.it168.com/j/2007-07-19/200707191542718_1.shtml
以上是自己的理解,不当之处请指正....!

 

 

另外装载了一篇

使用的Dwr版本2.0
在一台服务器上的不同端口上部署了同样的程序(tomcat5.5.28 80端口,tomcat 5.5.28 8080端口)
使用浏览器先后登陆80,8080端口的程序,都不注销,保持会话状态。
然后浏览器切换到8080的一个使用了DWR ajax功能的页面上,浏览器弹出Session Error的提示。
但是,如果切换到80端口的程序上,同样进入到一个使用了dwr ajax技术的页面上,没有Session Error的提示。
问题诊断:
初步怀疑浏览器的问题。
检查浏览器的cookie中的jsessionid的值。因为我们知道,Http协议本身是无状态的,服务器标识同一次会话的过程就是借助于cookie中的某个值或者通过url重写的方式来实现。这也是jsp程序的session原理。
检查发现:cookie中存在2个sessionid项,sessionid的值不同。
因为站点地址相同,url也相同(除了端口不同外),因此,浏览器“误”认为是同一个程序,把缓存的cookie项都发送回了服务器。
然后再观测ajax请求的值,即http post或get的参数值如下:


 

 callCount=1page=/web/initRolePermission.actionhttpSessionId=3F5F7D7C14D40667FF126DC6F9038EE5scriptSessionId=5B2B53E512648E78C92393E052589CA3859c0-scriptName=adminRolePerActionc0-methodName=findPermissionc0-id=0c0-param0=string:181batchId=0在这里,务必注意httpSessionId=3F5F7D7C14D40667FF126DC6F9038EE5,实际上,一般情况下,httpSessionId和cookie中的jsession值是相同的。至于dwr组件中,为什么要加上httpSessionId,这是因为dwr开发团队考虑到了跨站攻击问题。因此,通过验证dwr ajax请求中的httpSessionId值,来防止跨站攻击。在重现,诊断问题过程中,发现Session Error的信息是来自dwr ajax请求的响应中,抛出的异常是java.lang.SecurityException,因此可以怀疑这个错误信息是源于dwr源代码中的。用Eclipse打开下载到的dwr源代码。搜索Session Error的信息,然后在org.directwebremoting.dwrp.Batch 类中找到了,其部分代码如下:private void checkNotCsrfAttack(HttpServletRequest request, String sessionCookieName){// A check to see that this isn't a csrf attack// http://en.wikipedia.org/wiki/Cross-site_request_forgery// http://www.tux.org/~peterw/csrf.txtif (request.isRequestedSessionIdValid() && request.isRequestedSessionIdFromCookie()){String headerSessionId = request.getRequestedSessionId();if (headerSessionId.length() > 0){String bodySessionId = getHttpSessionId();// Normal case; if same session cookie is supplied by DWR and// in HTTP header then all is okif (headerSessionId.equals(bodySessionId)){return;}// Weblogic adds creation time to the end of the incoming// session cookie string (even for request.getRequestedSessionId()).// Use the raw cookie insteadCookie[] cookies = request.getCookies();for (int i = 0; i < cookies.length; i++){Cookie cookie = cookies[i];if (cookie.getName().equals(sessionCookieName) &&cookie.getValue().equals(bodySessionId)){return;}}// Otherwise errorlog.error("A request has been denied as a potential CSRF attack.");throw new SecurityException("Session Error");}}}仔细分析这段代码,即使在上述问题情境环境中,也不会出现Session Error的错误。然后反编译正在使用的dwr类文件,找到batch类,代码却不同,代码如下:private void checkNotCsrfAttack(HttpServletRequest request){if(request.isRequestedSessionIdValid() && request.isRequestedSessionIdFromCookie()){String headerSessionId = request.getRequestedSessionId();if(headerSessionId.length() > 0){String bodySessionId = getHttpSessionId();if(!bodySessionId.startsWith(headerSessionId))throw new SecurityException("Session Error");}}}该代码没有考虑到cookie中出现多个jsession的情况。到此,问题就发现并解决。由于dwr低版本的bug引起的,升级dwr版本即解决此问题。可能,读者还有一个疑问:为什么该问题只出现在8080端口上。检查发现:80端口的cookie项(就是80端口产生的jsessionid出现在cookie项的最前面),这样在80端口上的程序访问中,dwr ajax请求中的httpSessionId和cookie项最前面的jsessionid值相同,在80端口上,就自然不会出现session error错误。
0 0
原创粉丝点击