dwr框架的session error错误

在使用DWR框架时,出现错误截图如下:


在网上找了一些资料,找到了解决办法:

web.xml配置中加入

<span style="font-family:Microsoft YaHei;font-size:14px;"><init-param>
    <param-name>crossDomainSessionSecurity</param-name>
    <param-value>false</param-value>
</init-param></span>
经测试,问题完美解决,老师说换成Tomcat6.0也可以解决这个问题

这是同源策略的问题,为了WEB环境的安全,在WEB脚本语言中不允许读取不同源的数据,同源包括相同协议相同域名相同端口三个条件,而Ajax的异步处理方式跳过了这个限制,为了安全限制,它设置为sameDomainAccess。

又找了一些资料分析了一下:

使用的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=1
page=/web/initRolePermission.action
httpSessionId=3F5F7D7C14D40667FF126DC6F9038EE5
scriptSessionId=5B2B53E512648E78C92393E052589CA3859
c0-scriptName=adminRolePerAction
c0-methodName=findPermission
c0-id=0
c0-param0=string:181
batchId=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.txt
    if (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 ok
            if (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 instead
            Cookie[] 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 error
            log.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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值