spring boot 捕获filter异常 统一返回处理结果

如前面的文章所述,controller中抛出的异常我们使用ControllerAdvice来处理:

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(value = Exception.class)
    public AjaxResponse handler(Exception e){
        AjaxResponse r = new AjaxResponse();
        if (e instanceof RuntimeException){
            RuntimeException selectNoFindException = (RuntimeException) e;
            r.setStatus(-1);
            r.setMsg(selectNoFindException.getMessage());
        } else {
            r.setStatus(-1);
            r.setMsg("系统错误");
        }
        log.error(e.getMessage());
        return r;
    }

    /**
     * 捕获自定义异常
     * @param e
     * @return
     */
    @ExceptionHandler(value = FriendlyException.class)
    public Map<String,Object> errorHandle(FriendlyException e){
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("code",e.getCode());
        map.put("msg",e.getMsg());
        return map;
    }
}

 

但是filter中抛出的异常上面的方法就为无能为力了,如登录的认证,和权限的判断,我们可以使用如下的处理方法:

定义一个controller 继承BasicErrorController,并重写error方法。

@RestController
@Api(value = "handle filter throws exception", description = "处理filter抛出的异常")
public class ErrorController extends BasicErrorController {

    public ErrorController() {
        super(new DefaultErrorAttributes(), new ErrorProperties());
    }

    @Override
    @RequestMapping(produces = {MediaType.APPLICATION_JSON_VALUE})
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
        HttpStatus status = getStatus(request);

        Map<String,Object> map = new HashMap<String,Object>();
        map.put("code",body.get("status"));
        map.put("msg",body.get("message"));
        return new ResponseEntity<Map<String, Object>>(map, status);
    }
}

看下request中的信息:

看一下body中的信息:

 

接下来就可以filter中抛出异常,errorcontroller就可以捕获了:

 以下是shiro中认证失败时方法onAccessDenied:

    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
        HttpServletResponse httpResponse = WebUtils.toHttp(servletResponse);
        httpResponse.setCharacterEncoding("UTF-8");
        httpResponse.setContentType("application/json;charset=UTF-8");
        httpResponse.setStatus(HttpStatus.SC_NON_AUTHORITATIVE_INFORMATION);

        fillCorsHeader(WebUtils.toHttp(servletRequest), httpResponse);

        throw new AuthenticationException("token认证失败");
        //return false;
    }

以下是权限判断时,权限不足时抛出的异常在isAccessAllowed方法中。

    protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object mappedValue) throws Exception {
        Subject subject = getSubject(servletRequest, servletResponse);
        String[] rolesArray = (String[]) mappedValue;
        //没有角色限制,有权限访问
        if (rolesArray == null || rolesArray.length == 0) {
            return true;
        }
        for (String role : rolesArray) {
            //若当前用户是rolesArray中的任何一个,则有权限访问
            if (subject.hasRole(role)) {
                return true;
            }
        }
        throw new AuthorizationException("没有权限访问此资源");
    }

这里isAccessAllowed和onAccessDenied应该在哪个方法抛出异常呢,我没有考虑太多,都试了一下,有机会时再研究一下

 

posted @ 2019-03-13 12:46  二奎  阅读(5481)  评论(0编辑  收藏  举报