shiro doGetAuthenticationInfo 后端拦截异常,并向前端返回json结果
重点代码块:
/**
* 无需转发,直接返回Response信息
*/
private void response401(ServletResponse response, String msg) {
HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("application/json; charset=utf-8");
try (PrintWriter out = httpServletResponse.getWriter()) {
Result result = ResultFactory.buildUnauthorizedResult("无权访问(Unauthorized):" + msg);
JSONObject jsonObject = JSONUtil.parseObj(result);
out.append(jsonObject.toString());
} catch (IOException e) {
throw new CustomException("直接返回Response信息出现IOException异常:" + e.getMessage());
}
}
.........
/**
* 一般在isAccessAllowed中执行认证逻辑
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue){
if (isLoginAttempt(request, response)) {
try {
executeLogin(request, response);
} catch (Exception e) {
// 认证出现异常,传递错误信息msg
String msg = e.getMessage();
// Token认证失败直接返回Response信息
this.response401(response, msg);
return false;
}
}
return true;
}
/**
* 创建JWTFilter实现前端请求统一拦截及处理
* 所有的请求都会先经过 Filter,所以我们继承官方的 BasicHttpAuthenticationFilter
* 并且重写鉴权的方法
* 代码的执行流程 preHandle -> isAccessAllowed -> isLoginAttempt -> executeLogin
*
* @author GreenHatHG
**/
public class JWTFilter extends BasicHttpAuthenticationFilter {
/**
* 登录标识
*/
private static String LOGIN_SIGN = "Authorization";
/**
* 检测用户是否登录
* 检测header里面是否包含Authorization字段即可
*
* @param request
* @param response
* @return
*/
@Override
protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
HttpServletRequest req = (HttpServletRequest) request;
String authorization = req.getHeader(LOGIN_SIGN);
return authorization != null;
}
/**
* executeLogin() 方法中的 getSubject(request, response).login(token)
* 就是触发 Shiro Realm 自身的登录控制,具体内容需要手动实现
*
* @param request
* @param response
* @return
* @throws Exception
*/
@Override
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String authorization = httpServletRequest.getHeader(LOGIN_SIGN);
JWTToken token = new JWTToken(authorization);
// 提交给realm进行登入,如果错误他会抛出异常并被捕获
getSubject(request, response).login(token);
// 如果没有抛出异常则代表登入成功,返回true
return true;
}
/**
* 一般在isAccessAllowed中执行认证逻辑
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue){
if (isLoginAttempt(request, response)) {
try {
executeLogin(request, response);
} catch (Exception e) {
// 认证出现异常,传递错误信息msg
String msg = e.getMessage();
// Token认证失败直接返回Response信息
this.response401(response, msg);
return false;
}
}
return true;
}
/**
* 这里我们详细说明下为什么重写
* 可以对比父类方法,只是将executeLogin方法调用去除了
* 如果没有去除将会循环调用doGetAuthenticationInfo方法
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
this.sendChallenge(request, response);
return false;
}
/**
* 对跨域提供支持
*/
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
// 跨域时会首先发送一个OPTIONS请求,这里我们给OPTIONS请求直接返回正常状态
if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
httpServletResponse.setStatus(HttpStatus.OK.value());
return false;
}
return super.preHandle(request, response);
}
/**
* 无需转发,直接返回Response信息
*/
private void response401(ServletResponse response, String msg) {
HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("application/json; charset=utf-8");
try (PrintWriter out = httpServletResponse.getWriter()) {
Result result = ResultFactory.buildUnauthorizedResult("无权访问(Unauthorized):" + msg);
JSONObject jsonObject = JSONUtil.parseObj(result);
out.append(jsonObject.toString());
} catch (IOException e) {
throw new CustomException("直接返回Response信息出现IOException异常:" + e.getMessage());
}
}
}