springboot 实现切面校验请求参数

1、定义切面类

package com.aa.aa.pp.interceptor;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sgit.ois.framework.entity.WrappedResult;
import com.sgit.ois.pp.exception.ProcessException;
import com.sgit.ois.pp.util.CommonUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.aspectj.weaver.ast.Var;
import org.springframework.context.annotation.Configuration;

import java.util.*;
import java.util.regex.Pattern;

@Aspect
@Configuration
public class AspectPP1 {

    @Pointcut("execution(* com.aa.aa.pp.controller.*.*(..))")
    public void all(){}//这个是controller包下的所有请求接口都拦截

    @Pointcut("execution(* com.aa.aa.pp.controller.productSupplier.ProductSupplierController.save*(..))")
    public void pointCut20(){}//只拦截ProductSupplierController下以save开头的接口

	//前置切面生效的接口,||或的形式,也可以用&&,具体的execution定义也可以百度查查
	//下面的方法其实就是获取传递的参数的校验,可以按照自己的业务需求走,return这个没什么作用,只要没异常,都会将原有的请求参数传递到接口,自己定义全局异常可以拦截到并抛出页面
    @Before("all()|| pointCut20() ")
    public Object intercept(JoinPoint joinPoint) throws Throwable {
//        try {
//            //获取方法参数值数组
//            Object[] args = joinPoint.getArgs();
//            //得到其方法签名
//            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
//            //获取方法参数类型数组
//            Class[] paramTypeArray = methodSignature.getParameterTypes();
//            String[] parameterNames = methodSignature.getParameterNames();
//
//            Map params = new HashMap<>();
//            for (int i = 0; i < args.length; i++) {
//                params = judgeParam(args[i],parameterNames[i]);
//                modifyParameterValues(params);
//                args[i] = changeParam(params,args[i],parameterNames[i],paramTypeArray[i]);
//            }
//            //动态修改其参数
//            //注意,如果调用joinPoint.proceed()方法,则修改的参数值不会生效,必须调用joinPoint.proceed(Object[] args)
//        } catch (Throwable e) {
//            return WrappedResult.wrap(false, e.getMessage(), null, "保存的数据实体不能为空");
//        }
//        return WrappedResult.wrap(true, "", null, "保存的数据实体不能为空");
        //获取方法参数值数组




        if (joinPoint == null){
            return "";
        }
        Object[] args = joinPoint.getArgs();
        //得到其方法签名
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        //获取方法参数类型数组
        Class[] paramTypeArray = methodSignature.getParameterTypes();
        String[] parameterNames = methodSignature.getParameterNames();

        Map<String,Object> params = new HashMap<>();
        for (int i = 0; i < args.length; i++) {
            params = judgeParam(args[i],parameterNames[i]);
            modifyParameterValues(params);
            args[i] = changeParam(params,args[i],parameterNames[i],paramTypeArray[i]);
        }
//        String text = CommonUtils.decryptToText(m2Data);
        //动态修改其参数
        //注意,如果调用joinPoint.proceed()方法,则修改的参数值不会生效,必须调用joinPoint.proceed(Object[] args)
        return "text";
    }

    private Object changeParam(Map<String, Object> params, Object arg, String parameterName,Class paramTypeArray) {
        if ((arg instanceof String) || (arg instanceof Map) || (arg instanceof List)){ //参数为String、Map、List
            arg = params.get(parameterName);
            return arg;
        }
        arg = JSONObject.toJavaObject((JSON) JSON.toJSON(params),paramTypeArray);
        return arg;
    }

    private Map<String, Object>  judgeParam(Object arg,String parameterName) throws Throwable {
        Map<String,Object> params = new HashMap<>();
        if ((arg instanceof String) || (arg instanceof Map) || (arg instanceof List)){ //参数为String、Map、List
            params.put(parameterName,arg);
        }else{
            params = new ObjectMapper().readValue(JSON.toJSONString(arg), new TypeReference<HashMap<String, Object>>() {});
        }

        return params;
    }

    /**
     * 将parameter的值去除特殊字符后重写回去
     */
    public void modifyParameterValues(Map<String,Object> params)throws Exception{
        Set<String> set = params.keySet();
        Iterator<String> it=set.iterator();
        while(it.hasNext()){
            String key= it.next();
            if ("m2Data".equals(key)){
                String s = CommonUtils.decryptToText((String) params.get(key));
                Map<String,Object> map = (Map<String,Object>)JSON.parse(s);
                recursiveReplaceCharacter(map);
            }
            //处理参数
            getValueByKey(params,key);
        }
    }

    private void getValueByKey(Map<String,Object> params,String key) throws Exception{
        Object value = judgeObject(params.get(key));
        params.put(key,value);
    }

    private Object recursiveReplaceCharacter(Map<String, Object> vo) throws Exception{
        Map<String, Object> replaceMap = new HashMap<>();
        for(String key : vo.keySet()){//keySet获取map集合key的集合  然后在遍历key即可
            Object replaceMapValue = vo.get(key);
            Object a = judgeObject(replaceMapValue);
            replaceMap.put(key,a);
        }
        return replaceMap;
    }
    private static final String PASSWORD_PATTERN = "[<>?,/《》?;':‘’”;\\{\\}\\[\\]|、~!@#$%^&*()+`——]";
    Pattern pattern = Pattern.compile(PASSWORD_PATTERN);
//    private static Pattern speStrPattern = Pattern.compile(injectionCharacter(), Pattern.CASE_INSENSITIVE);

    private Object judgeObject(Object replaceMapValue) throws Exception{
        if (null == replaceMapValue) {
            //key对应的值为空
            return null;
        }
        if (replaceMapValue instanceof String) {
            //key对应的值为String类型, 去空格后重新放入map
            String s = replaceMapValue.toString();
            boolean b = pattern.matcher(s).find();
            if (b){
//                try {
//                    throw  new ProcessException("包含特殊字符");
//                } catch (ProcessException e) {
//                    throw new RuntimeException(e);
//                }
                throw  new ProcessException("包含特殊字符");
//                throw new ProcessException("包含特殊字符");
//                return WrappedResult.wrap(false, "保存的数据实体不能为空", null, "保存的数据实体不能为空");
            }
            return CharacterUtils.replaceBankParameter((String) replaceMapValue);
        } else if (replaceMapValue instanceof Map) {
            return recursiveReplaceCharacter((Map<String,Object>) replaceMapValue);
        } else if (replaceMapValue instanceof List) {
            //key对应的值为List类型
            List<Object> alist = (List<Object>) replaceMapValue;
            for (int i = 0; i < alist.size(); i++) {
                //遍历list
                Object vol = alist.get(i);
                if (vol instanceof String) {
                    //list里的元素为String, 去空格
                    alist.set(i, CharacterUtils.replaceBankParameter((String) vol));
                } else if (vol instanceof Map) {
                    //list里的元素为Map, 递归处理
                    alist.set(i, recursiveReplaceCharacter((Map<String,Object>) vol));
                }
            }
            return alist;
        }
        return replaceMapValue;
    }
}

2、全局异常捕获

package com.wang.test.annotation;

import com.wang.test.utils.Result;
import lombok.extern.slf4j.Slf4j;
import org.omg.CORBA.SystemException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
 
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    @ExceptionHandler(SystemException.class)
    public Result systemExceptionHandler(SystemException e) {
        log.error("出现了异常! {}", e);
        return Result.nok(e.getCause().getMessage());
    }
    @ExceptionHandler(Exception.class)
    public Result exceptionHandler(Exception e) {
        log.error("出现了异常! {}", e);
        return Result.nok(e.getCause().getMessage());
    }
    /* 添加校验参数异常处理 */
    @ExceptionHandler(BindException.class)
    public Result bindExceptionHandler(BindException e) {
        log.error("出现了异常! {}", e);
        return Result.nok(e.getCause().getMessage());
    }
}

你可能感兴趣的:(spring,boot,java,dubbo)