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,如图:
解决方案:
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标识,所以这里有点不不解。