欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ajax请求Session失效问题

程序员文章站 2022-06-03 15:08:26
最近由于一个项目,模块切换为ajax请求数据,当session失效后,ajax请求后没有返回值,只有响应的html:

最近由于一个项目,模块切换为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请求的头信息中,如下所示:

ajax请求Session失效问题ajax请求Session失效问题

上面两张图片是用火狐的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();
       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(, "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/index.html';      
       }
     }
   }
 });
 /**
 * 在页面中任何嵌套层次的窗口中获取顶层窗口
 * @return 当前页面的顶层窗口对象
 */
 function gettopwinow(){
   var p = window;
   while(p != p.parent){
     p = p.parent;
   }
   return p;
 }

以上内容是小编跟大家分享的ajax请求session失效问题,希望对大家有用。