Как использовать фильтр и генерировать пользовательское исключение с помощью Spring? - PullRequest
0 голосов
/ 13 марта 2020

У меня есть класс, который реализует фильтр. Я хочу выдать ошибку 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.

1 Ответ

0 голосов
/ 14 марта 2020

Существует несколько способов, но один из них - перехватить исключение GenericRestException в вашем фильтре и просто установить правильный код состояния в вашем ответе, а также, возможно, написать сообщение об ошибке с правильным типом содержимого.

(Примечание : код ниже предполагает, что GenericRestException имеет код состояния и ошибки)

try {

    } catch (GenericRestException e) {
       resp.setStatus(e.getStatusCode());
       resp.setContentType("application/json");
       resp.getWriter().print(e.getErrors());
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...