(转)EXT结合acegi解决ajax提交时session失效的有关问题
背景
B/S系统中,客户端向服务器端提交的http请求,可以分为两种:非ajax请求(一般http请求)和ajax请求。Acegi是通过一系列的filter实现的安全框架(现在好像升级成spring sceurity了)。对于非ajax请求时的session失效,acegi已经完成,即如果session失效则自动跳转到登录页面。
解决方案
Acegi对于session失效(或其他web异常)的处理是通过“org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint”类来实现的,具体配置如下:
<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter"> <property name="authenticationEntryPoint"> <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"> <property name="loginFormUrl" value="/login.jsp"/> <property name="forceHttps" value="false"/> </bean> </property> </bean>
如代码所示,acegi检测到session失效时就跳转到登录页面“/login.jsp”。实际上不管是非ajax请求还是ajax请求,acegi都是这么处理的。不过因为ajax不能实现页面跳转,所以这时的session失效处理的办法就“失效”了,客户在提交ajax后会得不到正确的处理或提示。解决这个问题的关键在于把两种http请求区分开来。本人对http的原理了解不深,笨人用笨办法,请出Ext(封装了ajax的一个js框架,其他js框架按照同样的原理理论上也可以实现)来:
Ext.Ajax.on('beforerequest', function(){ Ext.Ajax.extraParams={'ajax_extraParams':'true'}; }, this);//
如以上代码所示,EXT在ajax提交前和处理完成后提供了事件接口,分别是“'beforerequest'”和“'requestcomplete'”,我们就在这两个事件上想办法。对所有的ajax请求,我们都加上一个特殊的参数用以与非ajax请求区分“Ext.Ajax.extraParams={'ajax_extraParams':'true'};”。除此之外,我们还需acegi的辅助,修改它处理session失效时的几个参数配置:
<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter"> <property name="authenticationEntryPoint"> <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"> <property name="loginFormUrl" value="/checkLogin.jsp"/> <property name="forceHttps" value="false"/> <property name="serverSideRedirect" value="true"/> </bean> </property> </bean>
与前面提到的acegi配置相比,修改了两个地方:"loginFormUrl"修改成"/checkLogin.jsp",即检测到失效后跳转的路径;增加了一个"serverSideRedirect"属性并将其配置成true,即采用“forward”方式跳转(false则才用“redirect”方式跳转),之所以要采用“forward”方式是因为我们需要获取前面由EXT提交过来用以检测ajax请求的参数“ajax_extraParams”。
这样跳转到“checkLogin.jsp”后,我们就可以根据是否ajax请求作出我们自己的处理了:
<% String extraParams=request.getParameter("ajax_extraParams"); System.out.println("extraParams:"+extraParams); if("true".equals(extraParams)){ out.print("{ajax_session_invalid:true}"); return; } String contextPath = request.getContextPath(); response.sendRedirect(contextPath+"/login.jsp"); %>
代码里面读取“ajax_extraParams”参数,如果没有此参数,则直接跳转到登录页面;如有且为“true”我们就认为是ajax请求,则把session失效的标记以json的方式写会客户端,最后由EXT来处理:
Ext.Ajax.on('requestcomplete', function(conn,response){ try{ var resp=Ext.decode(response.responseText); if(resp.ajax_session_invalid){ alert("请重新登陆!") location=g_rootPath+"login.jsp"; } }catch(e){ } }, this);
以上代码即EXT在ajax完成事件通过“ajax_session_invalid”属性来检测是否session失效,如果失效则提示用户,然后跳转到登录界面。
后记
整个解决方案里面需要注意两个地方:acegi的"serverSideRedirect"属性必须是“1.0.3”及其以后的版本才有;另外一个就是我们的两个参数名(ajax_extraParams和ajax_session_invalid)必须比较特殊,以与业务属性区分。
转自:http://javaphoon.iteye.com/blog/375043