easyui shiro session超时跳转至登录页

 问题描述:java web项目中使用shiro做安全框架,前端使用easyui;在session过期时shiro配置了自动跳转至登录页面url,由于使用了easyui在前端做数据的展示、表单的提交等操作,于是出现session过期时使用easyui访问某个操作不会跳转至登录页面。easyui操作代码如下:

$("#formxx").form("submit", {
		url : 'addEntityurl',
		type : 'json',
		onSubmit : function(param) {
			var isValid = $(this).form("validate");
			if (!isValid) {
				$.messager.progress("close");
			}
			return isValid;
		},
		success : function(data) {
			var data = eval('(' + data + ')');
			if (data.code > 0) {
				$.messager.alert("提示", "保存成功");
			}
		}
	});
 shiro代码如下:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<property name="securityManager" ref="securityManager" />
		<property name="loginUrl" value="/login" />
		<!-- 登录成功页面,登录成功后跳转到该页面  -->
        <property name="successUrl" value="/index"/>
</bean>
 

具体原因:

      1,shiro配置的loginUrl在session过期时跳转至登录页面url的过程是针对普通数据访问方式的情况下,在异步数据访问方式下需要另外处理。

       2,easyui的onSumbit表单提交方法也不是异步ajax方式,而是重新生成了一个iframe,然后用的submit提交,也就是说其就是一个ajax的架子,实际上在Request Header中根本没有异步方法的参数标识:X-Requested-With:XMLHttpRequest,如图:
easyui shiro session超时跳转至登录页
 

解决方案:

       1,第一步,针对异步ajax的访问情况,可以在项目中添加一个Filter,判断在过期的情况下当前访问url是否为ajax请求url(通过Request Header中的异步方法参数标识:X-Requested-With:XMLHttpRequest),如果是ajax请求,然后在Response Header中添加一个参数:sessionstatus:timeout;第二步,写一个全局js文件,通过$.ajaxSetup设置AJAX的全局默认配置,即获取Response Header参数:sessionstatus,如果sessionstatus==timeout,则跳至登录页。

       2,不使用easyui的onSumbit表单提交方式,可采用jquery.ajax方式即可。

解决方案完整代码如下:

    一、自定义filter的代码:

@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		// TODO Auto-generated method stub
		HttpServletRequest httpRequest = (HttpServletRequest)request;
		HttpServletResponse httpResponse = (HttpServletResponse)response;
		String requestUrl = httpRequest.getRequestURI().replace(httpRequest.getContextPath(), "");
		
		//不过滤图片验证码路径、短信路径
		if(!requestUrl.contains("/createImg") && !requestUrl.contains("/getPhoneMsg") && !SecurityUtils.getSubject().isAuthenticated()){
			if(null != httpRequest.getHeader("X-Requested-With") && httpRequest.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")){
				//在ajax响应头部设置一个sessionstatus状态,用于在ajax全局js(common.js)中判断
				httpResponse.setHeader("sessionstatus", "timeout");
				httpResponse.getWriter().print("timeout");//
				return;
			}
		}
		
		chain.doFilter(request, response);
	}

   二、全局js代码:

$.ajaxSetup({
	error : function(XMLHttpRequest, textStatus, errorThrown){
		if(XMLHttpRequest.status == 403){
			alert('您没有权限访问此资源');
			return false;
		}
	},
	complete : function(XMLHttpRequest, textStatus){
		var sessionStatus = XMLHttpRequest.getResponseHeader("sessionstatus");
		console.log("sessionStatus= "+sessionStatus);
		if(sessionStatus == 'timeout'){
			var top = getTopWindow();
			top.location.href = '<c:url value="/" />';
		}
	}

});

function getTopWindow(){
	var p = window;
	while (p != p.parent){
		p = p.parent;
	}
	return p;
}

    三、异步表单提交代码:

function saveEntity(index) {
        //不使用easyui的onsubmit方法,新ajax方式是:先对表单做验证,再提交
	if(validate("formxx")){
		$.ajax({
			type : 'POST',
			url:'addentityurl',
			data:$('#formxx').serialize(),
			success : function(data) {
				if (data.code > 0) {
					$.messager.alert("提示", "保存成功");
				}
			}
		});
	}
}

function validate(id){
    var validate = $("#"+id).form('validate');
    if(!validate){
    	$.messager.alert("确认", '请正确填写表单!',"",function(){
    		$("#"+id).find(".validatebox-invalid:first").focus();
        });
        return false;
    }
    return true;
}

以上这种方式如果表单中有附件需要上传,则无法实现,因此建议使用jquery.easyui+jquery.form插件,代码如下:

function saveEntity(index) {
	//此为jquery.form插件的提交方法
	$("#formxx").ajaxSubmit({
		type: "POST",
		url:"addurl",
		dataType: "json",
		beforeSubmit: function(a,form,options){
			//此为easyui的表单验证
			var isValid = $("#formxx").form("validate");
			if (!isValid) {
				$.messager.progress("close");
			}
			
			return isValid;
		},
	    success: function(data){
			if (data.code > 0) {
				$.messager.alert("提示", "保存成功");
			} else {
				$.messager.alert("提示", "保存失败");
			}
		}
	});
	
}

  总之:感觉被easyui的表单提交方法给坑了,说是异步的,根本不是;比如easyui官网说是另外有一种ajax的表单提交方法:

$('#ff').form({
    url:...,
    onSubmit: function(){
		// do some check
		// return false to prevent submit;
    },
    success:function(data){
		alert(data)
    }
});
// submit the form
$('#ff').submit();

 但是我通过chrome查看Request Header,里面根本没有X-Requested-With:XMLHttpRequest标识,所以这里有点不不解。

相关推荐