一、认证授权失败处理
我们的项目在认证出错或者权限不足的时候响应回来的Json是Security的异常处理结果。但是这个响应的格式肯定是不符合我们项目的接口规范的。所以需要自定义异常处理。
AuthenticationEntryPoint 认证失败处理器
AccessDeniedHandler 授权失败处理器
我们只要实现这两个接口就行
@Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
authException.printStackTrace();
//InsufficientAuthenticationException
//BadCredentialsException
ResponseResult result = null;
if(authException instanceof BadCredentialsException){
result = ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_ERROR.getCode(),authException.getMessage());
}else if(authException instanceof InsufficientAuthenticationException){
result = ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
}else{
result = ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR.getCode(),"认证或授权失败");
}
//响应给前端
WebUtils.renderString(response, JSON.toJSONString(result));
}
}
@Component
public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
accessDeniedException.printStackTrace();
ResponseResult result = ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH);
//响应给前端
WebUtils.renderString(response, JSON.toJSONString(result));
}
}
然后在SecurityConfig配置类配置Security异常处理器
//配置异常处理器
http.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.accessDeniedHandler(accessDeniedHandler);
二、统一异常处理
实际我们在开发过程中可能需要做很多的判断校验,如果出现了非法情况我们是期望响应对应的提示的。但是如果我们每次都自己手动去处理就会非常麻烦。我们可以选择直接抛出异常的方式,然后对异常进行统一处理。把异常中的信息封装成ResponseResult响应给前端。
自定义系统运行时异常
public class SystemException extends RuntimeException{
private int code;
private String msg;
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
public SystemException(AppHttpCodeEnum httpCodeEnum) {
super(httpCodeEnum.getMsg());
this.code = httpCodeEnum.getCode();
this.msg = httpCodeEnum.getMsg();
}
}
统一异常处理(全局异常处理器):所有的异常都会交给这个全局异常去处理
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(SystemException.class)
public ResponseResult systemExceptionHandler(SystemException e){
//打印异常信息
log.error("出现了异常! {}",e);
//从异常对象中获取提示信息封装返回
return ResponseResult.errorResult(e.getCode(),e.getMsg());
}
@ExceptionHandler(Exception.class)
public ResponseResult exceptionHandler(Exception e){
//打印异常信息
log.error("出现了异常! {}",e);
//从异常对象中获取提示信息封装返回
return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR.getCode(),e.getMessage());
}
}
测试:
@RestController
public class BlogLoginController {
@Autowired
private BlogLoginService blogLoginService;
@PostMapping("/login")
public ResponseResult login(@RequestBody User user){
//如果用户名为空,就会抛出SystemException异常交给全局异常处理器去处理
if (!StringUtils.hasText(user.getUserName())){
throw new SystemException(AppHttpCodeEnum.REQUIRE_USERNAME);
}
return blogLoginService.login(user);
}
}
用postmen测试发现没有输入用户名就会提示这个消息