Shiro 处理ajax请求拦截登录超时
配置全局ajax配置
- $.ajaxSetup({
- complete:function(XMLHttpRequest,textStatus){
- if(textStatus=="parsererror"){
- $.messager.alert('提示信息', "登陆超时!请重新登陆!", 'info',function(){
- window.location.href = 'login.jsp';
- });
- } else if(textStatus=="error"){
- $.messager.alert('提示信息', "请求超时!请稍后再试!", 'info');
- }
- }
- });
在js里面配置全局的ajax配置即可!
Shiro session超时页面跳转的处理
问题描述
shiro在管理session后,在session超时会进行跳转,这里有两种情况需要考虑,一种是ajax方式的请求超时,一种页面跳转请求的超时。
本文从这两个方面分别考虑并处理。
ajax请求超时处理
思路:通过Filter后判定,当前是否session超时,超时判定是否是ajax请求,如果是ajax请求,则在response头部设置session-status值,返回到前端读取到相应值后进行处理
后端Filter代码
- package com.cnpc.framework.filter;
- import org.apache.shiro.SecurityUtils;
- import org.apache.shiro.session.Session;
- import javax.servlet.*;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
- /**
- * * filter过滤器,获取项目路径,设置ajax超时标识
- * @author billJiang QQ:475572229
- */
- public class SystemFilter implements Filter {
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException,
- ServletException {
- HttpServletRequest request = (HttpServletRequest) servletRequest;
- HttpServletResponse response = (HttpServletResponse) servletResponse;
- System.out.println(request.getRequestURL());
- String basePath = request.getContextPath();
- request.setAttribute("basePath", basePath);
- if (!SecurityUtils.getSubject().isAuthenticated()) {
- //判断session里是否有用户信息
- if (request.getHeader("x-requested-with") != null
- && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
- //如果是ajax请求响应头会有,x-requested-with
- response.setHeader("session-status", "timeout");//在响应头设置session状态
- return;
- }
- }
- filterChain.doFilter(request, servletResponse);
- }
- @Override
- public void destroy() {
- // TODO Auto-generated method stub
- }
- @Override
- public void init(FilterConfig arg0) throws ServletException {
- // TODO Auto-generated method stub
- }
- }
前端通用ajax处理
注意session-status上下文部分
- function ajaxPost(url, params, callback) {
- var result = null;
- var headers={};
- headers['CSRFToken']=$("#csrftoken").val();
- $.ajax({
- type : 'post',
- async : false,
- url : url,
- data : params,
- dataType : 'json',
- headers:headers,
- success : function(data, status) {
- result = data;
- if(data&&data.code&&data.code=='101'){
- modals.error("操作失败,请刷新重试,具体错误:"+data.message);
- return false;
- }
- if (callback) {
- callback.call(this, data, status);
- }
- },
- error : function(err, err1, err2) {
- console.log("ajaxPost发生异常,请仔细检查请求url是否正确,如下面错误信息中出现success,则表示csrftoken更新,请忽略");
- console.log(err.responseText);
- if(err && err.readyState && err.readyState == '4'){
- var sessionstatus=err.getResponseHeader("session-status");
- if(sessionstatus=="timeout"){
- //如果超时就处理 ,指定要跳转的页面
- window.location.href=basePath+"/" ;
- }
- else{//csrf异常
- var responseBody = err.responseText;
- if (responseBody) {
- responseBody = "{'retData':" + responseBody;
- var resJson = eval('(' + responseBody + ')');
- $("#csrftoken").val(resJson.csrf.CSRFToken);
- this.success(resJson.retData, 200);
- }
- return;
- }
- }
- modals.error({
- text : JSON.stringify(err) + '<br/>err1:' + JSON.stringify(err1) + '<br/>err2:' + JSON.stringify(err2),
- large : true
- });
- }
- });
- return result;
- }
非ajax请求超时跳转
在本试验中,使用jquery.load方式进行了页面加载,并重载jquery.fn.load改写了该方法,通过beforeSend去除了ajax标识,由于超时返回的登录页面可能嵌入当前页面,所以需要判断当前获得的页面是否是登录页面,如果是登陆页面,则再经过一次跳转到登陆页(或者首页)。
重载的jquery.fn.load方法如下,注意beforeSend和responseText.startWith部分内容。
- var _old_load = jQuery.fn.load;
- jQuery.fn.load = function( url, params, callback ) {
- //update for HANZO, 2016/12/22
- if (typeof url !== "string" && _old_load) {
- return _old_load.apply( this, arguments );
- }
- var selector, type, response,
- self = this,
- off = url.indexOf( " " );
- if ( off > -1 ) {
- selector = jQuery.trim( url.slice( off ) );
- url = url.slice( 0, off );
- }
- if ( jQuery.isFunction( params ) ) {
- callback = params;
- params = undefined;
- } else if ( params && typeof params === "object" ) {
- type = "POST";
- }
- if ( self.length > 0 ) {
- jQuery.ajax( {
- url: url,
- beforeSend: function( xhr ) {
- xhr.setRequestHeader('X-Requested-With', {toString: function(){ return ''; }});
- },
- type: type || "GET",
- dataType: "html",
- data: params
- } ).done( function( responseText ) {
- //console.log(responseText);
- response = arguments;
- //页面超时跳转到首页
- if(responseText.startWith("<!--login_page_identity-->")){
- window.location.href=basePath+"/";
- }else{
- self.html(selector ?
- jQuery("<div>").append(jQuery.parseHTML( responseText )).find(selector) :
- responseText);
- }
- } ).always( callback && function( jqXHR, status ) {
- self.each( function() {
- callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
- } );
- } );
- }
- return this;
- };
可通过设置session的timeout来测试结果。需要注意的是ajax请求要使用ajaxPost方法,该方法统一处理了超时跳转。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持w3xue。