ajax请求Session失效问题
最近由于一个项目,模块切换为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(); 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失效问题,希望对大家有用。