繁体   English   中英

如何使用过滤器并在 Spring 中抛出自定义异常?

[英]How to use filter and throw a custom exception with Spring?

我有一个实现过滤器的类。 我想抛出一个 http 错误 401。问题是它总是抛出 500。我该怎么办?

这是实现过滤器的类:

@Component
public class JwtAuthenticationFilter implements Filter {
    private static final Logger LOGGER = LoggerFactory.getLogger(JwtAuthenticationFilter.class);
    @Autowired
    TokenAuthenticationService tokenAuthenticationService;

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        if (request.getRequestURI().equals("/") || request.getRequestURI().equals("") ||
                request.getRequestURI().contains("authenticate") ||
                request.getRequestURI().contains("create") ||
                request.getRequestURI().contains("delete") || request.getRequestURI().contains("hystrix.stream")) {
            chain.doFilter(request, response);

        } else if (request.getRequestURI().contains("refresh")) {
            this.tokenAuthenticationService.getAuthentication(request, TokenTypeEnum.REFRESH);
            chain.doFilter(request, response);

        } else {
            this.tokenAuthenticationService.getAuthentication(request, TokenTypeEnum.ACCESS);
            chain.doFilter(request, response);
        }
    }
}

这是可以抛出 401 的类:

@Service
public class TokenAuthenticationService {
    private static Logger logger = LoggerFactory.getLogger(TokenAuthenticationService.class);
    static final String TOKEN_PREFIX = "Bearer";
    static final String HEADER_STRING = "Authorization";
    static final String PROJECT = "ProjectId";
    @Autowired
    public ProjectService projectService;

    public Authentication getAuthentication(HttpServletRequest request, TokenTypeEnum typeKey) {
        String token = request.getHeader(HEADER_STRING);
        String projectId = request.getHeader(PROJECT);
        Project project = projectService.findById(projectId);

        if (project == null) {
            logger.error("Project ID[{}] not found", projectId);
            throw new GenericRestException(HttpStatus.BAD_REQUEST, StringUtils.isBlank(projectId) ?
                    Exceptions.PROJECT_REQUIRED : Exceptions.PROJECT_NOTFOUND);
        }

        if (StringUtils.isBlank(token)) {
            logger.error("Authorization is required.");
            throw new GenericRestException(HttpStatus.BAD_REQUEST, Exceptions.AUTH_REQUIRED);
        }

        String authorizationToken = new Util().getBearerToken(token);
        if (StringUtils.isBlank(authorizationToken)) {
            logger.error("Authorization type invalid.");
            throw new GenericRestException(HttpStatus.BAD_REQUEST, Exceptions.AUTH_INVALID);
        }

        try {
            logger.debug("Parse JWT");
            Claims claims = Jwts.parser()
                    .setSigningKey(DatatypeConverter
                            .parseBase64Binary(typeKey.equals(TokenTypeEnum.ACCESS) ?
                                    project.getAccessKey() : project.getRefreshKey()))
                    .parseClaimsJws(authorizationToken).getBody();
            SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(claims.getSubject(), null, Collections.emptyList()));
            return new UsernamePasswordAuthenticationToken(claims.getSubject(), null, Collections.emptyList());
        } catch (ExpiredJwtException e) {
            logger.error("ExpiredJwtException - {}", e.getMessage(), e);
            throw new GenericRestException(HttpStatus.UNAUTHORIZED, Exceptions.EXPIRED_TOKEN);
        } catch (SignatureException e) {
            logger.error("SignatureException - {}", e.getMessage(), e);
            throw new GenericRestException(HttpStatus.UNAUTHORIZED, Exceptions.INVALID_SIGNATURE);
        }
    }
}

因此,当令牌过期时,我想抛出 http 状态为 401 的异常,以便客户端可以以正确的方式处理。 问题是总是返回 500。

有多种方法,但其中之一是在过滤器中捕获 GenericRestException 并简单地在响应中设置正确的状态代码,并可能使用正确的内容类型编写错误消息。

(注意:下面的代码假设 GenericRestException 有一个状态码和错误)

尝试 {

    } catch (GenericRestException e) {
       resp.setStatus(e.getStatusCode());
       resp.setContentType("application/json");
       resp.getWriter().print(e.getErrors());
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM