上篇Spring boot+Security OAuth2 爬坑日记(4)自定义异常处理 上 我们处理了认证服务的自定义异常,接下来我们接着处理资源服务的自定义异常
自定义OAuth2AuthenticationEntryPoint
该接口处理Token相关的异常,处理类如下
public class HttpUtils {
public static void writerError(BaseResponse bs, HttpServletResponse response) throws IOException {
response.setContentType("application/json,charset=utf-8");
response.setStatus(bs.getStatus());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.writeValue(response.getOutputStream(),bs);
}
}
@Component
public class BootOAuth2AuthExceptionEntryPoint extends OAuth2AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
HttpUtils.writerError(HttpResponse.baseResponse(HttpStatus.UNAUTHORIZED.value(),
e.getMessage()),response);
}
}
自定义AccessDeniedHandler
处理权限相关异常
@Component
public class BootAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException ex) throws IOException, ServletException {
HttpUtils.writerError(HttpResponse.baseResponse(HttpStatus.FORBIDDEN.value(),"没有权限"),response);
}
}
将两个自定义的异常处理类配置到资源资源服务中
@Configuration
@EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter{
@Autowired
private AuthenticationEntryPoint point;
@Autowired
private BootAccessDeniedHandler handler;
@Autowired
private TokenStore tokenStore;
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenStore(tokenStore)
.resourceId("boot-server");
// 异常处理
resources.authenticationEntryPoint(point).accessDeniedHandler(handler);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest()
.access("#oauth2.hasAnyScope('all','select')");
}
}
上诉的两个异常处理都没有进入Controller内部,当我们的Controller内部出现异常时,我们的异常信息还是默认的处理方式,这里也需要接管下,Spring MVC 为我们提供了方便的处理方式,使用一个@RestControllerAdvice
注解即可,看如下实现
@RestControllerAdvice
public final class ExceptionAdviceHandler {
private final static String SERVER_ERROR_TXT = "服务器内部错误";
private final static String ARGUMENTS_ERROR_TXT = "参数错误";
private final static String BAD_REQUEST_TXT = "错误的请求";
@ExceptionHandler(value = Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public BaseResponse unKnowExceptionHandler() {
return this.serverErrorHandler();
}
@ExceptionHandler(value = RuntimeException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public BaseResponse runtimeExceptionHandler(RuntimeException ex) {
return this.serverErrorHandler();
}
/**
* 空指针异常
*/
@ExceptionHandler(NullPointerException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public BaseResponse nullPointerExceptionHandler(Exception e) {
e.printStackTrace();
return this.serverErrorHandler();
}
/**
* 类型转换异常
*/
@ExceptionHandler(ClassCastException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public BaseResponse classCastExceptionHandler() {
return this.serverErrorHandler();
}
/**
* IO异常
*/
@ExceptionHandler(IOException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public BaseResponse iOExceptionHandler() {
return this.serverErrorHandler();
}
/**
* 未知方法异常
*/
@ExceptionHandler(NoSuchMethodException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public BaseResponse noSuchMethodExceptionHandler() {
return this.serverErrorHandler();
}
/**
* 数组越界异常
*/
@ExceptionHandler(IndexOutOfBoundsException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public BaseResponse indexOutOfBoundsExceptionHandler() {
return this.serverErrorHandler();
}
/**
* 400错误
*/
@ExceptionHandler(value = HttpMessageNotReadableException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public BaseResponse requestNotReadable() {
return baseResponse(400, BAD_REQUEST_TXT);
}
/**
* 400错误 类型不匹配
*/
@ExceptionHandler({TypeMismatchException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
public BaseResponse requestTypeMismatch() {
return this.argumentsError();
}
/**
* 400错误 缺少参数
*/
@ExceptionHandler({MissingServletRequestParameterException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
public BaseResponse requestMissingServletRequest() {
return this.argumentsError();
}
@ExceptionHandler(value = MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public BaseResponse methodArgumentNotValidExceptionHandler() {
return baseResponse(400, "参数错误");
}
@ExceptionHandler(value = NotAuthorityException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public SimpleResponse notAuthority(NotAuthorityException ex) {
return this.authErrorHandler(2, ex.getMessage());
}
@ExceptionHandler(UsernameNotFoundException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public BaseResponse usernameNotFound(UsernameNotFoundException ex){
return baseResponse(400,ex.getMessage());
}
@ExceptionHandler(value = NotAuthException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public SimpleResponse notAuth(NotAuthException ex) {
return this.authErrorHandler(1, ex.getMessage());
}
@ExceptionHandler(value = AuthFailureException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public SimpleResponse authFieald(AuthFailureException ex) {
return this.authErrorHandler(1, ex.getMessage());
}
/**
* 405错误
*/
@ExceptionHandler({HttpRequestMethodNotSupportedException.class})
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
public BaseResponse request405(HttpServletResponse resp) {
return baseResponse(405, "请求方法不正确");
}
/**
* 406错误
*/
@ExceptionHandler({HttpMediaTypeNotAcceptableException.class})
@ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
public BaseResponse request406(HttpServletResponse resp) {
return baseResponse(405, "不接受该请求");
}
/**
* 500错误
*/
@ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public BaseResponse server500(HttpServletResponse resp,Exception e) {
return this.serverErrorHandler();
}
@ExceptionHandler(value = HttpMediaTypeNotSupportedException.class)
@ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
public BaseResponse httpMediaTypeNotSupportedExceptionHandler(HttpServletResponse resp) {
return baseResponse(415, "服务器无法处理请求附带的媒体格式");
}
@ExceptionHandler(value = ArgumentsFailureException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public BaseResponse argsErrorExceptionHandler(ArgumentsFailureException ex, HttpServletResponse response) {
return baseResponse(400, ex.getMessage());
}
/**
* 404
*/
@ExceptionHandler(value = NoHandlerFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public BaseResponse notFoundException(HttpServletResponse response) {
return baseResponse(404, "找不到服务");
}
@ExceptionHandler(value = ServerErrorException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public BaseResponse serverErrorExceptionHandler(HttpServletResponse response) {
return this.serverErrorHandler();
}
private BaseResponse serverErrorHandler() {
return baseResponse(500, SERVER_ERROR_TXT);
}
private BaseResponse argumentsError() {
return baseResponse(400, ARGUMENTS_ERROR_TXT);
}
/**
* @param code 1 认证错误(未认证)、2 未授权/没有权限
* @param msg
* @return
*/
private SimpleResponse authErrorHandler(int code, String msg) {
Map<String, Object> mp = new HashMap<>();
mp.put("code", code);
return simpleResponse(401, msg, mp);
}
}
最后Spring MVC 的404错误想让上述的处理方式捕获到,必须要在配置文件application.yml
中加如下配置
spring:
mvc:
throw-exception-if-no-handler-found: true
当spring MVC找不到对应的controller来处理请求时,就不会使用默认的方式处理了,直接抛出异常,就会被ExceptionAdviceHandler
捕获到;到这里自定义异常处理结束
微信公众号