Springboot拦截器统一失败场景响应码

场景:自定义拦截器进行accessToken鉴权校验。

1、新建自定义异常类:TokenException,并继承RuntimeException

public class TokenException extends RuntimeException{
	
	private static final long serialVersionUID = 1L;

	public TokenException() {
		
	}
	
	public TokenException(String message) {
		super(message);
	}
}

2、创建全局异常Handler,监控抛出TokenException的场景

@Slf4j
@RestControllerAdvice//使用@ControllerAdvice注解也可以
public class GlobalExceptionHandler {

   @ExceptionHandler(ConstraintViolationException.class)
    public  Resp<String> resolveConstraintViolationException(ConstraintViolationException ex){
        Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
        if(!CollectionUtils.isEmpty(constraintViolations)){
            StringBuilder msgBuilder = new StringBuilder();
            for(ConstraintViolation<?> constraintViolation :constraintViolations){
                msgBuilder.append(constraintViolation.getMessage()).append(",");
            }
            String errorMessage = msgBuilder.toString();
            if(errorMessage.length()>1){
                errorMessage = errorMessage.substring(0,errorMessage.length()-1);
            }
            log.warn("ConstraintViolationException请求参数校验异常:{}",errorMessage);
            return Resp.response(ResponseCode.REQUEST_ERROR, errorMessage);
        }
        log.warn("ConstraintViolationException请求参数校验异常:{}",ex.getMessage());
        return Resp.response(ResponseCode.REQUEST_ERROR, ex.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Resp<String> resolveMethodArgumentNotValidException(MethodArgumentNotValidException ex){
        List<ObjectError>  objectErrors = ex.getBindingResult().getAllErrors();
        if(!CollectionUtils.isEmpty(objectErrors)) {
            StringBuilder msgBuilder = new StringBuilder();
            for (ObjectError objectError : objectErrors) {
                msgBuilder.append(objectError.getDefaultMessage()).append(",");
            }
            String errorMessage = msgBuilder.toString();
            if (errorMessage.length() > 1) {
                errorMessage = errorMessage.substring(0, errorMessage.length() - 1);
            }
            log.warn("MethodArgumentNotValidException请求参数校验异常:{}",errorMessage);
            return Resp.response(ResponseCode.REQUEST_ERROR, errorMessage);
        }
        log.warn("MethodArgumentNotValidException请求参数校验异常:{}",ex.getMessage());
        return Resp.response(ResponseCode.REQUEST_ERROR, ex.getMessage());
    }
    
    @ExceptionHandler(TokenException.class)
	public Resp<String> tokenException(HttpServletRequest req, TokenException e){
		log.error("请求:{},拦截器校验不通过",req==null?"":req.getServletPath(),e);
		return Resp.response(ResponseCode.REQUEST_ERROR, "accessToken校验失败");//自定义拦截器校验失败抛出的异常
	}
    
    @ExceptionHandler(value=Exception.class)
	public Resp<String> defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
		log.error("请求:{},操作异常{}",req==null?"":req.getServletPath(),e);
		return Resp.response(ResponseCode.ERROR, "操作异常");//系统异常,需要后台查看
	}
}

3、最后在拦截器的代码逻辑中,若accessToken检验不通过,则抛出TokenException,这时全局异常监控就会返回设置的统一响应码:ResponseCode.REQUEST_ERROR。

@Component
@Slf4j
public class TokenV2Interception extends HandlerInterceptorAdapter {
	
	@Autowired
	private RedisUtil redisUtil;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws TokenException {
		if (handler instanceof HandlerMethod) {
			String accessToken = request.getParameter("accessToken");
			log.info("TokenV2Interception拦截路由:"+request.getServletPath()+"|accessToken:{}",accessToken);
			if(StringUtils.isBlank(accessToken)){
				log.info("拦截器校验不通过:token为null");
				throw new TokenException("拦截器校验不通过:token为null");
			}			
			String decode = AuthGenerator.decryptAES(accessToken, Constant.AES_4_ACCESS_TOKEN);
			if(StringUtils.isBlank(decode)){
				log.info("拦截器校验不通过:decode为null");
				throw new TokenException("拦截器校验不通过:decode为null");
			}
			String appId = decode.substring(decode.indexOf("&")+1);
			log.info("appId:{}",appId);
			if(StringUtils.isBlank(appId)){
				log.info("拦截器校验不通过:appId为空");
				throw new TokenException("拦截器校验不通过:appId为空");
			}
			
			String serverToken = (String) redisUtil.get(appId);
			if(StringUtils.isBlank(serverToken)){
				log.info("拦截器校验不通过:服务器token为null");
				throw new TokenException("拦截器校验不通过:服务器token为null");
			}

			if(!serverToken.equalsIgnoreCase(accessToken)){
				log.info("拦截器校验不通过:服务器token:{}与accessToken不相等,请求非法",serverToken);
				throw new TokenException("拦截器校验不通过:服务器token:{}与accessToken不相等,请求非法");
			}
			log.info("拦截器校验通过");
			return true;
		} else {
            return true;
        }
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值