如果是前后端不分离的项目,想要在filter返回相应的异常信息,可添加重定向,由接口返回异常信息内容。因为我用的是前后端分离,所以打算在onAccessDenied触发身份认证,获取具体异常信息。 以下是代码,如果有问题,麻烦指出... 也希望能帮助到有缘人... @Slf4j public class JwtFilter extends BasicHttpAuthenticationFilter { /** * 拦截器的前置 最先执行的 这里只做了一个跨域设置 * */ @Override protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception { log.debug("JwtFilter -----> preHandle() 方法执行"); return super.preHandle(request, response); } /** * preHandle 执行完之后会执行这个方法 * 再这个方法中 我们根据条件判断去去执行isLoginAttempt和executeLogin方法 * */ @Override protected boolean isAccessAllowed (ServletRequest request, ServletResponse response, Object mappedValue) { // 只有isAccessAllowed返回false才会执行onAccessDenied。这样就可以在onAccessDenied触发身份认证,获取具体异常信息 return false; } /** * 这里我们只是简单去做一个判断请求头中的token信息是否为空 * 如果没有我们想要的请求头信息则直接返回false * */ @Override protected boolean isLoginAttempt (ServletRequest request, ServletResponse response){ log.debug("JwtFilter -----> isLoginAttempt() 方法执行"); HttpServletRequest req = (HttpServletRequest) request; String token = req.getHeader("token"); if(ObjectUtils.isEmpty(token)){ token = request.getParameter("token"); } return ObjectUtils.isNotEmpty(token); } /** * 执行登陆 * 因为已经判断token不为空了,所以直接执行登陆逻辑 * 将token放入JwtToken类中去 * 然后getSubject方法是调用到了MyRealm的 执行方法 因为上面我是抛错的所有最后做个异常捕获就好了 * */ @Override protected boolean executeLogin (ServletRequest request, ServletResponse response) throws Exception { log.debug("JwtFilter -----> executeLogin() 方法执行"); HttpServletRequest req = (HttpServletRequest) request; String token = req.getHeader("token"); if(ObjectUtils.isEmpty(token)){ token = request.getParameter("token"); } JwtToken jwtToken = new JwtToken(token); //然后交给自定义的realm对象去登陆, 如果错误他会抛出异常并且捕获 log.debug("-----执行登陆开始-----"); try { getSubject(request, response).login(jwtToken); } catch (PwdOutDayException e) { throw e; } catch (Exception e) { throw e; } log.debug("-----执行登陆结束----- 未抛出异常"); return true; } private void unloginResult(ServletResponse response, String msg) throws Exception { response.setContentType("application/json;charset=utf-8");// json数据 response.getWriter().write(JSONObject.toJSON(Result.unlogin(msg)).toString()); } private void pwdOutDayResult(ServletResponse response, String msg) throws Exception { response.setContentType("application/json;charset=utf-8");// json数据 response.getWriter().write(JSONObject.toJSON(Result.pwdOutDay(msg)).toString()); } @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { //判断请求的请求头是否带上 "Token" if (isLoginAttempt(request, response)){ //如果存在,则进入 executeLogin 方法执行登入,检查 token 是否正确 try { executeLogin(request, response); return true; } catch (Exception e) { if(I18nUtil.getMsg("personalerr60020").equals(e.getMessage())){ // 这个是我用来判断密码过期异常的,可不要这块 pwdOutDayResult(response, e.getMessage()); } else { unloginResult(response, e.getMessage()); } } } else { unloginResult(response, I18nUtil.getMsg("syserr10046")); } // 返回false不会再执行其他过滤器 return false; } }
jwt继承BasicHttpAuthenticationFilter,无法捕获具体异常信息
于 2022-11-22 09:51:26 首次发布