当前位置: 移动技术网 > IT编程>脚本编程>Ajax > 完美解决ajax访问遇到Session失效的问题

完美解决ajax访问遇到Session失效的问题

2017年12月08日  | 移动技术网IT编程  | 我要评论
最近由于一个项目,模块切换为ajax请求数据,当session失效后,ajax请求后没有返回值,只有响应的html:<html><script type=

最近由于一个项目,模块切换为ajax请求数据,当session失效后,ajax请求后没有返回值,只有响应的html:<html><script type='text/javascript'>window.open('http://192.168.0.118:8080/welcomeaction/loginui.do','_top');</script></html>

现在ajax在web项目中应用广泛,几乎可以说无处不在,这就带来另外一个问题:当ajax请求遇到session超时,应该怎么办?

显而易见,传统的页面跳转在此已经不适用,因为ajax请求是xmlhttprequest对象发起的而不是浏览器,在验证失败后的页面跳转无法反应到浏览器中,因为服务器返回(或输出)的信息被javascript(xmlhttprequest对象)接到了。

那么应该怎么处理这种情况呢?

方法

既然服务器返回的消息被xmlhttprequest对象接收,而xmlhttprequest对象又是在javascript的掌控之中,那么我们是否可以利用javascript来完成页面跳转呢?

当然可以,而且很容易实现!但有一点,我们需要判断一下http请求是否为ajax请求(因为ajax请求和普通的请求需要分开处理),这又如何判断呢?其实ajax请求和普通的http请求是不同的,这体现在http请求的头信息中,如下所示:

上面两张图片是用火狐的firebug截取的,前者是普通的http请求头信息;后者为ajax请求的请求头信息。注意第一图片被红框圈起来的部分,这就是ajax请求与普通请求不同的地方,ajax请求头中带有x-requested-with信息,其值为xmlhttprequest,这正是我们可以利用的地方。

下面看一下代码如何实现。

interceptor过滤器

在使用struts2时,我们一般使用interceptor(拦截器)来拦截权限问题。

拦截器部分代码:

public string intercept(actioninvocation invocation) throws exception {
    // todo auto-generated method stub
    actioncontext ac = invocation.getinvocationcontext();
    httpservletrequest request = (httpservletrequest) ac.get(strutsstatics.http_request);
    string requesttype = request.getheader("x-requested-with");
    system.out.println("+++++++++++++++++++++++reqesttype:"+requesttype);
    httpservletresponse response = (httpservletresponse) ac.get(strutsstatics.http_response);
//    string basepath = request.getcontextpath();
    string path = request.getcontextpath(); 
    string basepath = request.getscheme()+"://"+request.getservername()+":"+request.getserverport()+path; 
    //获取session
    map session = ac.getsession();
    //判断session是否存在及session中的user信息是否存在,如果存在不用拦截
    if(session != null && session.get(constants.fe_session_bg_user) != null && session.get(constants.fe_session_bg_auth) != null){
      system.out.println(invocation.getproxy().getactionname()+"++++++++++++++++++++++++");
      system.out.println("namespace:"+invocation.getproxy().getnamespace());
      //访问路径
      string visiturl = invocation.getproxy().getnamespace() + "/" + invocation.getproxy().getactionname() + constants.fe_struts_action_extension;
      visiturl = visiturl.substring(1);
      map<string , object> authmap = (map<string, object>) session.get(constants.fe_session_bg_auth);
      map<integer, string> actionmap = (map<integer, string>) authmap.get(constants.fe_bg_actionmap);
      if(actionmap != null && !actionmap.isempty() && visiturl != null){
        if (actionmap.containsvalue(visiturl)) {
          system.out.println(visiturl+"-----------------------");
          return invocation.invoke();
        } else{
          string forbidden = basepath + constants.fe_bg_forbidden;
          response.sendredirect(forbidden);
          return null;
        }
      }
      return invocation.invoke();
    }else{
      if(stringutils.isnotblank(requesttype) && requesttype.equalsignorecase("xmlhttprequest")){
        response.setheader("sessionstatus", "timeout"); 
        response.senderror(518, "session timeout."); 
        return null;
      }else {
        
        string actionname = invocation.getproxy().getactionname();
        system.out.println(actionname);
        //如果拦截的actionname是loginui或login,则不做处理,否则重定向到登录页面
        if (stringutils.isnotblank(actionname) && actionname.equals(constants.fe_bg_loginui)) {
          return invocation.invoke();
        }else if(stringutils.isnotblank(actionname) && actionname.equals(constants.fe_bg_login)){
          return invocation.invoke();
        }else{
          string login = basepath + "/" + constants.fe_bg_login_namespace + "/" + constants.fe_bg_loginui + constants.fe_struts_action_extension;
//        system.out.println("+++++++++++++++++++++++++++basepath:"+basepath);
//        response.sendredirect(login);
          printwriter out = response.getwriter();
//        out.println("<html>"); 
//        out.println("<script>"); 
//        out.println("window.open ('"+login+"','_top');"); 
//        out.println("</script>"); 
//        out.println("</html>");
          out.write("<html><script type='text/javascript'>window.open('"+login+"','_top');</script></html>");
          return null;
        }
      }
    }
    
  }

由上面代码可以看出,当session验证失败(即session超时)后,我们通过httpservletrequest取得请求头信息x-requested-with的值,如果不为空且等于xmlhttprequest,那么就说明此次请求是ajax请求,我们作出的反应就是向响应中添加一条头信息(自定义)并且使响应对象httpservletresponse返回服务器错误信息(518状态是自己随便定义的);这些信息都会被javascript接收,那么下面的工作就要将由javascript代码了。

javascript代码

$.ajaxsetup方法是来设置ajax请求默认选项的,我们可以认为是全局的选项设置,因此可以将这段代码提到外部js文件中,在需要的页面引用。

/**
 * 设置未来(全局)的ajax请求默认选项
 * 主要设置了ajax请求遇到session过期的情况
 */
$.ajaxsetup({
  type: 'post',
  complete: function(xhr,status) {
    var sessionstatus = xhr.getresponseheader('sessionstatus');
    if(sessionstatus == 'timeout') {
      var top = gettopwinow();
      var yes = confirm('由于您长时间没有操作, session已过期, 请重新登录.');
      if (yes) {
        top.location.href = '/skynk/';      
      }
    }
  }
});

/**
 * 在页面中任何嵌套层次的窗口中获取顶层窗口
 * @return 当前页面的顶层窗口对象
 */
function gettopwinow(){
  var p = window;
  while(p != p.parent){
    p = p.parent;
  }
  return p;
}

以上这篇完美解决ajax访问遇到session失效的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持移动技术网。

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网