今天在測試shiro的時候發現 shiro 的 AuthenticationException 異常無法被 統一異常處理類處理
這是統一異常處理
這裏無法處理 在 MyRealm 當中的異常 爲啥呢 ?
原因 :
我在這裏捕獲到了我想要的異常 是 shiro 整合完 jwt 之後的過濾器 BasicHttpAuthenticationFilter
這是他的繼承鏈路
最終繼承到了 servlet 的 Filter 類 Filter 處理是在 控制器之前的 所以 @ControllerAdvice 由spring 提供的增強控制器是無法處理這個異常的 。
解決方案
我在 Filter 當中使用 httpServletResponse.sendRedirect 重定向到 我自定義的一個 控制器當中
/**
* 將非法請求跳轉到 /unauthorized/**
*/
private void responseError(ServletResponse response, String message) {
try {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
//設置編碼,否則中文字符在重定向時會變爲空字符串
message = URLEncoder.encode(message, "UTF-8");
httpServletResponse.sendRedirect("/common/unauthorized/" + message);
} catch (IOException e) {
log.error(e.getMessage());
}
}
這是接收異常的控制器
@RestController
@RequestMapping("/common")
public class FilterErrorController {
@RequestMapping(path = "/unauthorized/{message}")
public Result unauthorized(@PathVariable String message) throws UnsupportedEncodingException {
return Result.build("401", message);
}
}
在這個控制器當中專門處理 Filter 當中的錯誤 。
這裏貌似解決問題了 但是發現一旦有異常 就陷入死循環了 不斷的拋出異常 到達指定控制器
原因 :
在配置 shiro 時 使用了 所有的請求都通過 JWTFilter 就是這段代碼 filterRuleMap.put("/**", "jwt"); 所以重定向的時候 異常被攔截 , 再次拋出異常 就會陷入死循環
解決 :
// 訪問 /unauthorized/** 不通過JWTFilter
filterRuleMap.put("/common/unauthorized/**", "anon");
配置上這一段 也就是說 不攔截我們需要拋出異常的請求