今天又發現了一個新的問題,Shiro的攔截器不能夠攔截ajax請求,需要自定義一個攔截器來攔截ajax請求。
package com.ssi.domains.secutity;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.servlet.AdviceFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Created by jay.zhou on 2018/3/27.
* 用于攔截ajax請求
* 預設的Shiro配置檔案中攔截規則對發送的ajax請求無效
* 是以必須自己做一個Shiro的過濾器
* 這樣的話,ajax請求也會被Shiro攔截到
* 本類可以預見到未來将會被複用多次
* see:http://jinnianshilongnian.iteye.com/blog/2025656
*/
public final class AjaxFilter extends AdviceFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(AjaxFilter.class);
/**
* 前處理,這裡用于判斷這此請求是不是ajax請求
*
*/
@Override
protected boolean preHandle(ServletRequest req, ServletResponse resp)
throws Exception {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
//擷取請求頭中的資訊,ajax請求最大的特點就是請求頭中多了 X-Requested-With 參數
String requestType = request.getHeader("X-Requested-With");
if("XMLHttpRequest".equals(requestType)){
LOGGER.info("本次請求是AJAX請求!");
//現在的用途就是判斷目前使用者是否被認證
//先擷取到由Web容器管理的subject對象
Subject subject = SecurityUtils.getSubject();
//判斷是否已經認證
boolean isAuthc = subject.isAuthenticated();
if(!isAuthc){
LOGGER.info("目前賬戶使用Shiro認證失敗!");
//如果目前賬戶沒有被認證,本次請求被駁回,ajax進入error的function中進行重定向到登入界面。
return false;
}
return true;
}else{
//如果請求類型不是ajax,那麼此時requestType為null
LOGGER.info("非AJAX請求!");
}
//預設傳回的是true,将本次請求繼續執行下去
return super.preHandle(request, response);
}
/**
* 後處理,類似于AOP中的後置傳回增強
* 在攔截器鍊執行完成後執行
* 一般用于記錄時間。
*/
@Override
protected void postHandle(ServletRequest request, ServletResponse response)
throws Exception {
super.postHandle(request, response);
}
/**
* 最終處理,一定會執行的,一般用于釋放資源。
* 先留着
*/
@Override
public void afterCompletion(ServletRequest request, ServletResponse response, Exception exception)
throws Exception {
super.afterCompletion(request, response, exception);
}
}
然後在配置檔案中配置上我們的攔截器即可。
[filters]
#預設的Shiro配置,對發送的ajax請求無效,是以需要自己做一個攔截器
myAjaxFilter=com.ssi.domains.secutity.AjaxFilter
[urls]
#評論子產品的操作需要登入
/actions/comment/**=myAjaxFilter,perms[comment]
希望能幫助你正在解決Shiro攔截不了ajax請求提供一個思路。
在網上好多同僚在攔截器中傳回了Json資料,原因是ajax請求裡面的request和response對象是不支援轉發或者重定向的。
我這裡沒有直接傳回Json資料,直接攔截住這個請求,沒有傳回success屬性,那麼ajax請求将會進入error的function中,執行重定向到登入頁面的操作。
如何判斷一個請求是ajax請求。編寫像下面的代碼,從請求頭中擷取此參數資訊。如果這個requestType的值是:XMLHttpRequest ,那麼這個請求是ajax請求。
String requestType = request.getHeader("X-Requset-With");
上圖為證明,本圖右下角。

按浏覽器F12,選中network,進入審查元素中,我們可以發現發送的accountLogin請求,是ajax請求。
在Request Headers 請求頭中的相關資訊中, X-Request-With 的值是 XMLHttpRequest。