首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Spring:如何使过滤器抛出自定义异常?

Spring:如何使过滤器抛出自定义异常?
EN

Stack Overflow用户
提问于 2017-05-18 06:58:23
回答 3查看 17.2K关注 0票数 6

我创建了一个过滤器,对JWT令牌的每个请求头进行身份验证:

代码语言:javascript
运行
复制
public class JWTAuthenticationFilter extends GenericFilterBean {

    private UserDetailsService customUserDetailsService;
    private static Logger logger = LoggerFactory.getLogger(JWTAuthenticationFilter.class);
    private final static UrlPathHelper urlPathHelper = new UrlPathHelper();

    public JWTAuthenticationFilter(UserDetailsService customUserDetailsService) {
        this.customUserDetailsService = customUserDetailsService;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        Authentication authentication = AuthenticationService.getAuthentication((HttpServletRequest) request, customUserDetailsService);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        if (authentication == null) {
            logger.debug("failed authentication while attempting to access " + urlPathHelper.getPathWithinApplication((HttpServletRequest) request));
        }
        filterChain.doFilter(request, response);
    }

}

我想抛出一个自定义异常,该异常返回一个响应:

代码语言:javascript
运行
复制
@ResponseStatus(value=HttpStatus.SOMECODE, reason="There was an issue with the provided authentacion information")  // 409
public class CustomAuthenticationException extends RuntimeException {

    private static final long serialVersionUID = 6699623945573914987L;

}

我该怎么做?捕捉过滤器抛出的这种异常的最佳设计是什么?Spring安全提供了什么类型的异常处理机制,我可以在一个点内使用和捕获所有的异常处理机制吗?是否有其他方法在筛选器中抛出自定义异常?

备注:还有另一个问题这里,它接受的答案没有回答我的问题。在到达任何控制器之前,我想返回一个响应。

我想要处理的错误情况: 1.客户端为授权头发送一个空值。2.客户端发送格式错误的令牌

在这两种情况下,我都会得到一个使用500 HTTP状态代码的响应。我要拿回4XX代码。

EN

回答 3

Stack Overflow用户

发布于 2017-05-18 07:04:18

看看@ControllerAdvice

下面是我的项目的一个例子。

代码语言:javascript
运行
复制
@ControllerAdvice
@RestController
public class GlobalExceptionHandler {

    private final Logger log = Logger.getLogger(this.getClass().getSimpleName());

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = RuntimeException.class)
    public Response handleBaseException(RuntimeException e) {
        log.error("Error", e);
        Error error = new Error(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.name());
        return Response.status(HttpStatus.BAD_REQUEST.value()).error(error, null).build();
    }

    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(value = NoHandlerFoundException.class)
    public Response handleNoHandlerFoundException(Exception e) {
        log.error("Error", e);
        Error error = new Error(HttpStatus.NOT_FOUND.value(), HttpStatus.NOT_FOUND.name());
        return Response.status(HttpStatus.NOT_FOUND.value()).error(error, null).build();
    }

    @ExceptionHandler(value = AuthenticationCredentialsNotFoundException.class)
    public Response handleException(AuthenticationCredentialsNotFoundException e) {     
        log.error("Error", e);
        Error error = new Error(ErrorCodes.INVALID_CREDENTIALS_CODE, ErrorCodes.INVALID_CREDENTIALS_MSG);
        return Response.status(ErrorCodes.INVALID_CREDENTIALS_CODE).error(error, null).build();
    }

    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    @ExceptionHandler(value = UnauthorisedException.class)
    public Response handleNotAuthorizedExceptionException(UnauthorisedException e) {        
//      log.error("Error", e);
        return Response.unauthorized().build();
    }

    @ExceptionHandler(value = Exception.class)
    public String handleException(Exception e) {
        log.error("Error", e);
        return e.getClass().getName() + " 14" + e.getMessage();
    }


}

编辑

我相信你可以在response.sendError里面做过滤方法。

代码语言:javascript
运行
复制
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
    Authentication authentication = AuthenticationService.getAuthentication((HttpServletRequest) request, customUserDetailsService);
    SecurityContextHolder.getContext().setAuthentication(authentication);
    if (authentication == null) {
        logger.debug("failed authentication while attempting to access " + urlPathHelper.getPathWithinApplication((HttpServletRequest) request));
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid authentication.");
        setUnauthorizedResponse(response);
        return;
    }
    filterChain.doFilter(request, response);
}

public void setUnauthorizedResponse(HttpServletResponse response) {
    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    response.setContentType("application/json");
    Response unAuthorizedResponse = Response.unauthorized().build();
    try {
        PrintWriter out = response.getWriter();
        out.println(unAuthorizedResponse.toJsonString());
    } catch (IOException e) {
        log.error("Error", e);
    }
}
票数 4
EN

Stack Overflow用户

发布于 2017-09-21 20:59:03

我对JWT令牌也有同样的问题,并在这个问题上发布了解决方案,因为这个问题类似(他在过滤器异常方面有问题)。

票数 0
EN

Stack Overflow用户

发布于 2021-07-07 06:29:54

免责声明:这不是问题的答案,但这是对Arian提出的问题的后续回答。

如上文所述,在春季容器允许我们访问bean之前,您可以在这些地方进行自动测试。

在这里,我正在自动完成我的BlacklistJwtRepo

代码语言:javascript
运行
复制
if (blacklistJwtRepo == null) { //Lazy Load because filter
        ServletContext servletContext = req.getServletContext();
        WebApplicationContext webApplicationContext =  WebApplicationContextUtils.getWebApplicationContext(servletContext);
        blacklistJwtRepo = webApplicationContext.getBean(BlacklistJwtRepo.class);
    }

我在这里找到了req对象-

代码语言:javascript
运行
复制
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;

最后的代码看起来-

代码语言:javascript
运行
复制
    @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;      
    System.out.println("blacklistJwtRepo : " + blacklistJwtRepo);
    //till here the autowired repo (blacklistJwtRepo) is null
    if (blacklistJwtRepo == null) { //Lazy Load because filter
        ServletContext servletContext = req.getServletContext();
        WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
        blacklistJwtRepo = webApplicationContext.getBean(BlacklistJwtRepo.class);
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44040703

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档