Springboot AOP一个神奇的问题,跨模块失效解决

文章讲述了在SpringBoot项目中,通过AOP切面处理appScan扫描出的API安全问题。问题源于前端参数与后端实体类参数不匹配。作者提出了一种解决方案,即创建AOP切面类,校验前端传递的参数是否为后端实体类的子集,通过Gson和JSONObject进行JSON对象的对比,排除特定字段,如果发现未知参数则抛出异常。为了解决AOP未生效的问题,添加了一个配置类并引入到启动类中。
摘要由CSDN通过智能技术生成
   先说一下问题,在appScan扫描出了几个API成批分批的安全问题。

在这里插入图片描述

这个问题的原因就是参数和后端定义的实体类的参数不同,前端参数应该是后端参数子集的一个关系。想了很多方法,既然参数问题,那我可以AOP直接拦截前端参数,然后跟后端进行对比,如果前端传过来的参数是后端定义不存在的,直接抛异常。

项目是springboot 项目,直接在common模块下面建一个aop包写切面类:

@Aspect
@Component
public class MastAspect {


    // @Pointcut("execution(* com.meehealth.emss.module.mast.controller..*.*(..))")
    @Pointcut("@annotation(com.meehealth.emss.framework.common.aop.InterfaceMate)")
    public void e() {
    }

    @Around("e()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        // 获取目标方法的入参
        Object[] args = point.getArgs();
        // 实体类json
        Object obj1 = args[0];

        // 获取被注解方法上的注解
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        InterfaceMate specialRequestAnnotation = methodSignature.getMethod().getAnnotation(InterfaceMate.class);
        // 获取注解中的值
        String value1 = specialRequestAnnotation.value();


        // 创建Gson对象
        Gson gson = new Gson();
        // 将Java对象(obj1)转换为JsonObject对象(jsonObject1)
        JsonObject jsonObject1 = new JsonObject();
        Class<?> clazz = obj1.getClass();
        while (clazz != null) {
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                Object value = field.get(obj1);

                // 检查字段名是否为需要排除的字段
                if(value1.equals("login")){
                if (field.getName().equals("tenantName") || field.getName().equals("rememberMe")) {
                    continue; // 跳过该字段
                }}

                jsonObject1.addProperty(field.getName(), gson.toJson(value));
            }
            clazz = clazz.getSuperclass();
        }





        // 从JoinPoint中获取Servlet请求
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        if(request==null){
            Object result = point.proceed();
            return result;
        }
        BufferedReader reader = request.getReader();
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        String requestData = sb.toString();
        org.json.JSONObject jsonObject2 = new org.json.JSONObject(requestData);

        // 排除特定字段
        if (value1.equals("login")) {
            Iterator<String> keys = jsonObject2.keys();
            while (keys.hasNext()) {
                String key = keys.next();

                // 检查字段名是否为需要排除的字段
                if (key.equals("tenantName") || key.equals("rememberMe")) {
                    keys.remove(); // 移除该字段
                }
            }
        }


        boolean isEqual = compare(String.valueOf(jsonObject1), String.valueOf(jsonObject2));

        if (isEqual == false) {
            throw exception(UNKNOWN_ATTRIBUTE_EXIST);
        }
        Object result = point.proceed();
        return result;

    }


    //Josn对比
    public static boolean compare(String json1, String json2) throws IOException {
        ObjectMapper mapper = new ObjectMapper();

        TypeReference<LinkedHashMap<String, Object>> typeRef =
                new TypeReference<LinkedHashMap<String, Object>>() {};

        LinkedHashMap<String, Object> map1 = mapper.readValue(json1, typeRef);
        LinkedHashMap<String, Object> map2 = mapper.readValue(json2, typeRef);

        return map1.keySet().containsAll(map2.keySet());
    }

}

项目启动后发现AOP并没有生效。
在这里插入图片描述
在翻阅了相关资料后发现国内还搜不到 ,是我搜索问题方法有问题?不过最后还是在stackoverflow找到了, 如果AOP如果跨模块需要加一个配置类。

项目结构:

parent-project     //项目名称
----common[Aop.class ,Config.class]   //aop切面
----controller[请求]                  //请求路径
----service[Application]             //启动类

Config.class 配置类


@Configuration
@ComponentScan("com.meehealth.emss.framework.common.aop")
public class Config {

    @Bean
    public MastAspect createAop() {
        return new MastAspect();
    }
}

在启动类上引入一下

@Import(Config.class)  //启动加主键,引入配置文件

然后AOP就可以使用了。
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值