请求参数加密的参数校验处理

实际开发中经常会遇到对外请求接口或者对外提供接口,对外提供接口时需要保证请求的安全性和参数的判断,最近应公司项目需求,需要开发一个开放平台,对外提供接口实现数据对接,约定数据加密方式采用AES加密。做了一套关于加密参数的校验。直接切入主题。

大致流程

加密参数校验,我的方案是采用自定义注解的方式实现。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ReqAop {

    /**
     * 返回数据是否加密
     *
     * @return
     */
    boolean aes() default false;

    /**
     * 是否参数校验
     *
     * @return
     */
    boolean valiedArgs() default false;

    /**
     * 需要获校验的类
     * @return
     */
    Class<? extends BaseDto> clazz() default BaseDto.class;
}

参数校验具体实现方法如下

	@Around("@annotation(reqAop)")
    public Object around(ProceedingJoinPoint pjp, ReqAop reqAop) throws Throwable {
        log.info("====>>>ReqAop aop 开始启动 ");

        List<String> validList = new ArrayList<>();
        String key = "wmsapi0123456789";

        String reqData;
        Object rvt;
        if (reqAop.valiedArgs()) {

            long start = System.currentTimeMillis();
            reqData =  validParamsByAnnotation(pjp, reqAop, validList, key);
            log.warn("===>参数校验耗时:{}ms,校验结果:{}, 解密结果:{}", System.currentTimeMillis() - start, JSON.toJSONString(validList), reqData);
            if (!CollectionUtils.isEmpty(validList)) {
                //参数校验不通过将错误信息存入日志
                return Result.validationError(ExceptionEnum.PARAMS_VALIED_ERROR.getCode(), validList);
            }

            if (StringUtils.isEmpty(reqData)) {
                return Result.validationError(ExceptionEnum.REQUEST_BODY_NOT_NULL.getMessage());
            }

            //设置请求体为解密之后的json串
            Object[] params = {reqData};
            rvt = pjp.proceed(params);
        }else {
            rvt = pjp.proceed();
        }

        if (!(rvt instanceof Result)) {
            log.error(ExceptionEnum.RES_MUST_RESULT.getMessage());
            throw new RuntimeException(ExceptionEnum.RES_MUST_RESULT.getMessage());
        }
        Result result = (Result) rvt;
        if (reqAop.aes()) {
            if (result.getCode() == HttpStatus.HTTP_OK && !Objects.isNull(result.getData())) {
                // 返回参数加密
                result.setData(AESCodeUtil.encode(JSON.toJSONString(result.getData()), key));
            }
        }
        return result;
    }

    private String validParamsByAnnotation(ProceedingJoinPoint pjp, ReqAop reqAop, List<String> validList, String key) {
        Object[] arguments = pjp.getArgs();
        if (Objects.isNull(arguments)) {
            throw new RuntimeException(ExceptionEnum.REQUEST_BODY_NOT_NULL.getMessage());
        }
        // 解密请求参数
        String decryValue;

        try {
            decryValue = AESCodeUtil.decode((String) arguments[0], key);
        } catch (Exception e) {
            log.error("===> 请求参数解密异常:{}", e);
            throw new RuntimeException(ExceptionEnum.PARAMS_DECODE_ERROR.getMessage());
        }

        if (decryValue == null) {
            throw new RuntimeException(ExceptionEnum.PARAMS_DECODE_ERROR.getMessage());
        }
        Object object = new JSONTokener(decryValue).nextValue();

        //获取需要校验的类信息
        Class claz = reqAop.clazz();
        if(object instanceof JSONObject){
            //存放解密参数信息
            Map<String, Object> paramMap = JSON.parseObject(decryValue);

            validField(paramMap, validList, claz);
        }else if (object instanceof JSONArray) {
            com.alibaba.fastjson.JSONArray jsonArray = JSON.parseArray(decryValue);

            for (Object o : jsonArray) {
                Map<String, Object> listParamMap = JSON.parseObject(JSON.toJSONString(o));
                validField(listParamMap, validList, claz);
            }

        }else {
            throw new RuntimeException();
        }

        return decryValue;
    }

    private void validField(Map<String, Object> paramMap, List<String> validList, Class clazz) {
        //获取需要校验类的全部属性信息
        Field[] fields = FieldUtils.getAllFields(clazz);
        for (Field field : fields) {
            //处理List类型属性
            if (List.class.isAssignableFrom(field.getType())) {
                Type t = field.getGenericType();
                if (t instanceof ParameterizedType) {
                    ParameterizedType pt = (ParameterizedType) t;
                    //得到对象list中实例的类型
                    Class clz = (Class) pt.getActualTypeArguments()[0];
                    Object o = null;
                    if (paramMap != null) {
                        o = paramMap.get(field.getName());
                    }
                    if (o != null) {
                        Object object = new JSONTokener(o.toString()).nextValue();
                        if (object instanceof cn.hutool.json.JSONArray) {
                            com.alibaba.fastjson.JSONArray jsonArray = JSON.parseArray(JSON.toJSONString(object));
                            for (Object o1 : jsonArray) {
                                //获取list对象的属性
                                Map<String, Object> listParamMap = JSON.parseObject(JSON.toJSONString(o1));
                                if (!listParamMap.isEmpty()) {
                                    //递归校验List参数信息
                                    validField(listParamMap, validList, clz);
                                }
                            }
                        }
                    }
                }
            }
            //获取参数值
            Object o = null;
            if (paramMap != null) {
                o = paramMap.get(field.getName());
            }
            //获取NotBlank注解
            NotBlank blank = field.getAnnotation(NotBlank.class);
            if (blank != null) {
                valideNull(validList, o, blank.message());
            }
            //获取NotNull注解
            NotNull notNull = field.getAnnotation(NotNull.class);
            if (notNull != null) {
                valideNull(validList, o, notNull.message());
            }
            Length length = field.getAnnotation(Length.class);
            if (length != null) {
                String val = o + "";
                if (val.length() > length.max()) {
                    validList.add(length.message());
                }
            }
            Pattern pattern = field.getAnnotation(Pattern.class);
            if (pattern != null) {
                if (StringUtils.isNotBlank(pattern.regexp()) && !Objects.isNull(o)) {
                    boolean flag = java.util.regex.Pattern.matches(pattern.regexp(), o.toString());
                    if (!flag) {
                        validList.add(pattern.message());
                    }
                }
            }
            FormatLimit formatLimit = field.getAnnotation(FormatLimit.class);
            if (formatLimit != null && !Objects.isNull(o) && StringUtils.isNotBlank(o.toString())) {
                String[] formates = formatLimit.forages();
                boolean contains = Arrays.asList(formates).contains(o.toString());
                if (!contains) {
                    validList.add(formatLimit.message());
                }
            }
            Min min = field.getAnnotation(Min.class);
            if (min != null && !Objects.isNull(o)) {
                if (o instanceof Integer) {
                    int val = Integer.parseInt(o + "");
                    if (val < min.value()) {
                        validList.add(min.message());
                    }
                }
            }
            DecimalMin decimalMin = field.getAnnotation(DecimalMin.class);
            if (decimalMin != null && !Objects.isNull(o)) {
                BigDecimal o1 ;
                if (o instanceof BigDecimal) {
                    o1 = (BigDecimal) o;
                    BigDecimal m = new BigDecimal(decimalMin.value());
                    if (o1.compareTo(m) < 0) {
                        validList.add(decimalMin.message());
                    }
                }else if (o instanceof Integer) {
                    o1 = new BigDecimal((Integer) o);
                    BigDecimal m = new BigDecimal(decimalMin.value());
                    if (o1.compareTo(m) < 0) {
                        validList.add(decimalMin.message());
                    }
                }
            }
        }
    }

    private void valideNull(List<String> validList, Object o, String message) {
        if (o instanceof String) {
            if (StringUtils.isBlank((String) o)) {
                validList.add(message);
            }
        } else {
            if (Objects.isNull(o)) {
                validList.add(message);
            }
        }
    }

项目代码地址:https://github.com/maduoduo52/encrypt_params_valid

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 JSP 中对登录时的 POST 请求参数进行 MD5 加密,可以使用以下代码: ```java <% String username = request.getParameter("username"); // 获取 username 参数值 String password = request.getParameter("password"); // 获取 password 参数值 String passwordMD5 = ""; // 用于存储加密后的密码 if (password != null && !password.equals("")) { // 将密码进行 MD5 加密 MessageDigest md5 = MessageDigest.getInstance("MD5"); byte[] bytes = md5.digest(password.getBytes()); StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(String.format("%02X", b)); } passwordMD5 = sb.toString(); } // 构造加密后的参数 String encryptedUsername = java.net.URLEncoder.encode(username, "UTF-8"); String encryptedPassword = java.net.URLEncoder.encode(passwordMD5, "UTF-8"); %> <form action="login.jsp" method="post"> <input type="text" name="username" value="<%=encryptedUsername%>"> <input type="password" name="password" value="<%=encryptedPassword%>"> <input type="submit" value="登录"> </form> ``` 其中,`request.getParameter("username")` 和 `request.getParameter("password")` 用于获取 POST 请求中的用户名和密码参数值,将密码进行 MD5 加密的代码与上面的例子相同,不再赘述。然后,构造加密后的参数值,使用 `java.net.URLEncoder.encode` 方法进行 URL 编码。 最后,将加密后的参数值设置到表单的输入框中,用户提交表单时,将会提交加密后的参数。在服务器端接收到请求后,需要对参数进行解密和校验,确保用户名和密码的正确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值