解決Shiro 處理ajax請(qǐng)求攔截登錄超時(shí)的問(wèn)題
Shiro 處理ajax請(qǐng)求攔截登錄超時(shí)
配置全局ajax配置
$.ajaxSetup({
complete:function(XMLHttpRequest,textStatus){
if(textStatus=="parsererror"){
$.messager.alert('提示信息', "登陸超時(shí)!請(qǐng)重新登陸!", 'info',function(){
window.location.href = 'login.jsp';
});
} else if(textStatus=="error"){
$.messager.alert('提示信息', "請(qǐng)求超時(shí)!請(qǐng)稍后再試!", 'info');
}
}
});
在js里面配置全局的ajax配置即可!
Shiro session超時(shí)頁(yè)面跳轉(zhuǎn)的處理
問(wèn)題描述
shiro在管理session后,在session超時(shí)會(huì)進(jìn)行跳轉(zhuǎn),這里有兩種情況需要考慮,一種是ajax方式的請(qǐng)求超時(shí),一種頁(yè)面跳轉(zhuǎn)請(qǐng)求的超時(shí)。
本文從這兩個(gè)方面分別考慮并處理。
ajax請(qǐng)求超時(shí)處理
思路:通過(guò)Filter后判定,當(dāng)前是否session超時(shí),超時(shí)判定是否是ajax請(qǐng)求,如果是ajax請(qǐng)求,則在response頭部設(shè)置session-status值,返回到前端讀取到相應(yīng)值后進(jìn)行處理
后端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過(guò)濾器,獲取項(xiàng)目路徑,設(shè)置ajax超時(shí)標(biāo)識(shí)
* @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里是否有用戶(hù)信息
if (request.getHeader("x-requested-with") != null
&& request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
//如果是ajax請(qǐng)求響應(yīng)頭會(huì)有,x-requested-with
response.setHeader("session-status", "timeout");//在響應(yīng)頭設(shè)置session狀態(tài)
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("操作失敗,請(qǐng)刷新重試,具體錯(cuò)誤:"+data.message);
return false;
}
if (callback) {
callback.call(this, data, status);
}
},
error : function(err, err1, err2) {
console.log("ajaxPost發(fā)生異常,請(qǐng)仔細(xì)檢查請(qǐng)求url是否正確,如下面錯(cuò)誤信息中出現(xiàn)success,則表示csrftoken更新,請(qǐng)忽略");
console.log(err.responseText);
if(err && err.readyState && err.readyState == '4'){
var sessionstatus=err.getResponseHeader("session-status");
if(sessionstatus=="timeout"){
//如果超時(shí)就處理 ,指定要跳轉(zhuǎn)的頁(yè)面
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請(qǐng)求超時(shí)跳轉(zhuǎn)
在本試驗(yàn)中,使用jquery.load方式進(jìn)行了頁(yè)面加載,并重載jquery.fn.load改寫(xiě)了該方法,通過(guò)beforeSend去除了ajax標(biāo)識(shí),由于超時(shí)返回的登錄頁(yè)面可能嵌入當(dāng)前頁(yè)面,所以需要判斷當(dāng)前獲得的頁(yè)面是否是登錄頁(yè)面,如果是登陸頁(yè)面,則再經(jīng)過(guò)一次跳轉(zhuǎn)到登陸頁(yè)(或者首頁(yè))。
重載的jquery.fn.load方法如下,注意beforeSend和responseText.startWith部分內(nèi)容。
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;
//頁(yè)面超時(shí)跳轉(zhuǎn)到首頁(yè)
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;
};
可通過(guò)設(shè)置session的timeout來(lái)測(cè)試結(jié)果。需要注意的是ajax請(qǐng)求要使用ajaxPost方法,該方法統(tǒng)一處理了超時(shí)跳轉(zhuǎn)。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java項(xiàng)目在Idea中開(kāi)發(fā)遇到所有代碼爆紅的問(wèn)題與解決辦法
今天打開(kāi)項(xiàng)目時(shí)發(fā)現(xiàn)idea竟然爆紅,通過(guò)查找相關(guān)資料用于解決,下面這篇文章主要給大家介紹了關(guān)于Java項(xiàng)目在Idea中開(kāi)發(fā)遇到所有代碼爆紅的問(wèn)題與解決辦法的相關(guān)資料,需要的朋友可以參考下2023-06-06
Spring?AOP實(shí)現(xiàn)多數(shù)據(jù)源動(dòng)態(tài)切換
本文主要介紹了Spring?AOP實(shí)現(xiàn)多數(shù)據(jù)源動(dòng)態(tài)切換,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
SpringBoot整合Redisson實(shí)現(xiàn)分布式鎖
本文主要介紹了SpringBoot整合Redisson實(shí)現(xiàn)分布式鎖,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
Spring?Boot如何排除自動(dòng)加載數(shù)據(jù)源
這篇文章主要介紹了Spring?Boot如何排除自動(dòng)加載數(shù)據(jù)源,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12

