自定义异常处理返回结果
Spring Security Oauth2通过WebResponseExceptionTranslator来处理用户认证时出现的异常,而在认证之前对客户端进行认证时和Spring Security认证流程没有太大差异。 自定义GlobalOauth2ExceptionHandler实现WebResponseExceptionTranslator,重写返回参数。
@Component
public class GlobalOauth2ExceptionHandler implements WebResponseExceptionTranslator<OAuth2Exception> {
private final ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer();
@Override
public ResponseEntity<OAuth2Exception> translate(Exception e) {
// Try to extract a SpringSecurityException from the stacktrace
Throwable[] causeChain = throwableAnalyzer.determineCauseChain(e);
Exception ase;
// 通过逐级判断异常类型进行相应的处理,和原生的DefaultWebResponseExceptionTranslator实现并无太大差异
ase = (UnsupportedGrantTypeException) throwableAnalyzer.getFirstThrowableOfType(UnsupportedGrantTypeException.class, causeChain);
if (ase != null) {
return handleOAuth2Exception(new ServerOauth2Exception("不支持的授权类型!!!", e));
}
ase = (AuthenticationException) throwableAnalyzer.getFirstThrowableOfType(AuthenticationException.class,
causeChain);
if (ase != null) {
return handleOAuth2Exception(new ServerOauth2Exception(e.getMessage(), e));
}
ase = (AccessDeniedException) throwableAnalyzer
.getFirstThrowableOfType(AccessDeniedException.class, causeChain);
if (ase != null) {
return handleOAuth2Exception(new ServerOauth2Exception(ase.getMessage(), ase));
}
ase = (HttpRequestMethodNotSupportedException) throwableAnalyzer.getFirstThrowableOfType(
HttpRequestMethodNotSupportedException.class, causeChain);
if (ase != null) {
return handleOAuth2Exception(new ServerOauth2Exception(ase.getMessage(), ase));
}
ase = (OAuth2Exception) throwableAnalyzer.getFirstThrowableOfType(
OAuth2Exception.class, causeChain);
if (ase != null) {
return handleOAuth2Exception((OAuth2Exception) ase);
}
return handleOAuth2Exception(new ServerOauth2Exception("服务器内部错误!!!", e));
}
private ResponseEntity<OAuth2Exception> handleOAuth2Exception(OAuth2Exception e) {
int status = e.getHttpErrorCode();
HttpHeaders headers = new HttpHeaders();
headers.set("Cache-Control", "no-store");
headers.set("Pragma", "no-cache");
if (status == HttpStatus.UNAUTHORIZED.value() || (e instanceof InsufficientScopeException)) {
headers.set("WWW-Authenticate", String.format("%s %s", OAuth2AccessToken.BEARER_TYPE, e.getSummary()));
}
return new ResponseEntity<>(e, headers,
HttpStatus.OK);
}
}
自定义异常类继承Oauth2Exception
通过自定义的异常类继承Oauth2Exception,只保留我们需要展示的信息,摒弃了Oauth2Exception原来展示的异常信息
@JsonSerialize(using = ServerOauth2ExceptionSerializer.class)
public class ServerOauth2Exception extends OAuth2Exception {
public ServerOauth2Exception(String msg) {
super(msg);
}
public ServerOauth2Exception(String msg, Throwable t) {
super(msg, t);
}
}
认证失败和授权失败处理器
@Component
public class GlobalAccessDeniedHandler implements AccessDeniedHandler {
private Logger logger = LoggerFactory.getLogger(GlobalAccessDeniedHandler.class);
// 自定义授权失败异常处理器
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
logger.error(accessDeniedException.getMessage());
R<Object> result = R.fail(HttpCodeStatus.FORBIDDEN, "授权失败,您暂时无法访问服务!!!");
response.setContentType("application/json;charset=UTF-8");
ServletOutputStream out = response.getOutputStream();
ObjectMapper objectMapper = new ObjectMapper();
out.write(objectMapper.writeValueAsBytes(result));
out.flush();
out.close();
}
}
@Component
public class GlobalAuthenticationEntryPoint implements AuthenticationEntryPoint {
private Logger logger = LoggerFactory.getLogger(GlobalAuthenticationEntryPoint.class);
// 自定义认证返回实体
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
logger.error(authException.getMessage());
R<Object> result = R.fail(HttpCodeStatus.UNAUTHORIZED, "认证失败,请检查账号密码!!!");
response.setContentType("application/json;charset=UTF-8");
ServletOutputStream out = response.getOutputStream();
ObjectMapper objectMapper = new ObjectMapper();
out.write(objectMapper.writeValueAsBytes(result));
out.flush();
out.close();
}
}