SpringMVC攔截器的配置及應用


前言

當用戶訪問我們的某些接口時,我們會去校驗用戶是否登錄或者是用戶是否有權限,比如我們一些管理員的功能就是不提供用戶使用的。
這一系列的校驗權限是很常用的,所以我們可以去配置SpringMVC攔截器,當用戶訪問我們的接口時,會自動的校驗權限。

 

1.在SpringMVC中配置上我們的攔截器以及攔截的路徑

 

  /*   當面路徑下的所有路徑,不包含子文件夾

  /**   指的是所有路徑以及里面的子路徑

  /   web項目的根目錄請求

 

 

 

2.配置我們的攔截器

 首先在我們要在存放攔截器的路徑下創建一個java類,隨后使該類實現接口(HandlerInterceptor)並實現接口中的三個方法

  2.1 preHandle()             攔截目標執行前,執行該方法。該方法有返回值(Boolean),若返回true則放行執行目標,若返回false則攔截不放行目標。

  2.2 postHandle()      攔截目標執行后,執行該方法

  2.3 afterCompletion()   攔截目標執行所有后,執行該方法

 

 問題一:在攔截器的配置上,當我們需要注意攔截的時候別攔截到登錄功能,當我們在進行管理員登錄的時候,調用了管理員登錄的接口。在調用的時候我們就被攔截器攔截了,此時我們還沒登錄就被攔截報錯了。

 

 

 所以我們應該想辦法解決攔截登錄的循環。

 

方法1:在springmvc配置文件中,編輯攔截器使之忽略攔截該路徑

 

 

方法2:在攔截器中加上邏輯判斷,當攔截到的目標,是對應類中的對應方法時,放行

//解析HandlerMethod
String methodName = handlerMethod.getMethod().getName();
String className = handlerMethod.getBean().getClass().getSimpleName();
if(StringUtils.equals(className,"UserManageController") && StringUtils.equals(methodName,"login")){
//如果是攔截到登錄請求,不打印參數,因為參數里面有密碼,全部會打印到日志中,防止日志泄露
log.info("權限攔截器攔截到請求,className:{},methodName:{}",className,methodName);
return true;
}

 

 

 

 

 

 

 

 

 

 

問題二: 在攔截器中我們統一設置了返回格式為Json,但是在我們產品的圖片上傳中有涉及到富文本上傳,富文本的上傳

返回值為Map形式,所以我們還需改進攔截器

 

解決方法:在返回值處細化返回內容。加入if判斷

if(user ==null){
if(StringUtils.equals(className,"ProductManageController") && StringUtils.equals(methodName,"richtextImgUpload")){
Map resultMap = Maps.newHashMap();
resultMap.put("success",false);
resultMap.put("msg","請登錄管理員");
out.print(JsonUtil.obj2String(resultMap));
}else {
out.print(JsonUtil.obj2String(ServerResponse.createByErrorMessage("攔截器攔截,用戶未登錄")));
}
}else{
if(StringUtils.equals(className,"ProductManageController") && StringUtils.equals(methodName,"richtextImgUpload")){
Map resultMap = Maps.newHashMap();
resultMap.put("success",false);
resultMap.put("msg","無權限操作");
out.print(JsonUtil.obj2String(resultMap));
}else {
out.print(JsonUtil.obj2String(ServerResponse.createByErrorMessage("攔截器攔截,無權限操作")));
}

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

注意:在做完攔截器后,修改原先Controller中的代碼時,需注意保留圖片上傳到FTPServer中的功能,

 

 

 

攔截器代碼:


@Slf4j
public class AuthorityInterceptor implements HandlerInterceptor {


@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("preHandle");
//請求中Controller中的方法名
HandlerMethod handlerMethod = (HandlerMethod) handler;

//解析HandlerMethod
String className = handlerMethod.getBean().getClass().getSimpleName();//請求目標類名
String methodName = handlerMethod.getMethod().getName();//請求目標方法名


//解析參數,具體的參數key以及value是什么,打印日志
StringBuffer requestParamBuffer = new StringBuffer();
Map paramMap = request.getParameterMap();//獲取請求參數Map

//遍歷Map,並且拼接成字符串
Iterator iterator = paramMap.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry entry = (Map.Entry)iterator.next();
String mapkey = (String)entry.getKey();
String mapValue = StringUtils.EMPTY;

//request這個參數的map(ParameterMap),里面的value返回的是一個String[]
Object obj = entry.getValue();
if(obj instanceof String[]){
String[] strs = (String[])obj;
mapValue = Arrays.toString(strs);
}
requestParamBuffer.append(mapkey).append("=").append(mapValue);

}

//放行管理員登錄接口,避免登錄循環
if(StringUtils.equals(className,"UserManageController") && StringUtils.equals(methodName,"login")){
//如果是攔截到登錄請求,不打印參數,因為參數里面有密碼,全部會打印到日志中,防止日志泄露
log.info("權限攔截器攔截到請求,className:{},methodName:{}",className,methodName);
return true;
}

//從Cookie中獲取到登錄的Token,然后去Redis中獲取出來登錄的用戶
User user = null;
String loginToken = CookieUtil.readLoginToken(request);

if(StringUtils.isNotEmpty(loginToken)){
String userJsonStr = RedisShardedPoolUtil.get(loginToken);
user = JsonUtil.string2Obj(userJsonStr,User.class);
}

//判斷用戶是否登錄 || 是否為管理員
if(user == null || (user.getRole().intValue() != Const.Role.ROLE_ADMIN) ){
//返回false即不會調用controller里的方法
//以下要更改返回值,首先重置response。
response.reset();//這里要添加reset,否則報異常 getWriter() has already been called for this response.
response.setCharacterEncoding("UTF-8");//由於response重置了,所以要重新設置編碼,否則會亂碼
response.setContentType("application/json;charset=UTF-8");//由於response重置了,所以要重新設置返回值的類型,因為全部是json接口。

PrintWriter out = response.getWriter();

if(user ==null){
out.print(JsonUtil.obj2String(ServerResponse.createByErrorMessage("攔截器攔截,用戶未登錄")));
}else{
out.print(JsonUtil.obj2String(ServerResponse.createByErrorMessage("攔截器攔截,無權限操作")));
}
out.flush();
out.close();//這里要關閉流

return false;
}
return true;
}

@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
log.info("postHandle");
}

@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
log.info("afterCompletion");
}
}

 

 

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM