简体   繁体   中英

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?

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:

@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. The problem is that is always returning 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.

(Note: the code below assumes GenericRestException has a statuscode and errors)

try {

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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