[英]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.