简体   繁体   English

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

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

I have a class that implements a filter.我有一个实现过滤器的类。 I want to throw a http error 401. The Problem is that it always throws 500. What do I have to do?我想抛出一个 http 错误 401。问题是它总是抛出 500。我该怎么办?

This is the class which implements the filter:这是实现过滤器的类:

@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);
        }
    }
}

This is the class which can throw a 401:这是可以抛出 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);
        }
    }
}

So when the token is expired, I want to throw the exception with the http status 401, so the clients can handle in the right way.因此,当令牌过期时,我想抛出 http 状态为 401 的异常,以便客户端可以以正确的方式处理。 The problem is that is always returning 500.问题是总是返回 500。

There are multiple ways, but one of them is to catch your GenericRestException in your filter and simply set the correct status code on your response and maybe write an error message with the right content type.有多种方法,但其中之一是在过滤器中捕获 GenericRestException 并简单地在响应中设置正确的状态代码,并可能使用正确的内容类型编写错误消息。

(Note: the code below assumes GenericRestException has a statuscode and errors) (注意:下面的代码假设 GenericRestException 有一个状态码和错误)

try {尝试 {

    } 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