AOP学习使用实战-使用AES

1.任务需求

在工作开发中,需要一个系统可以安卓端登录,也可以后台登录。但需要所有安卓端的请求和返回值都需要加密处理,后台请求值和返回值正常。

2.分析妥妥AOP

1.定义一个安卓方法的注解
//METHOD 说明该注解只能用在方法上
@Target(ElementType.METHOD)         
@Retention(RetentionPolicy.RUNTIME)
public @interface AndroidMethod {
}
2.根据需求写一个安卓切面

1.把注解 AndroidMethod 作为切点

2.因为需要对请求值和返回值进行加解密,所以使用环绕通知。

3.根据Req的不同,判断数据安卓请求还是后台请求。

@Aspect
@Component
public class AndroidAspect {
    @Autowired
    private HttpServletRequest httpServletRequest;

    //标注切点
    @Pointcut("@annotation(com.common.annotation.AndroidMethod)")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object Around(ProceedingJoinPoint joinPoint) throws Throwable {
        String req = httpServletRequest.getHeader("Req");
        //请求头 Req为1时是后台数据,不加解密,不为1时为安卓数据,需要解密
        if (!"1".equals(req)) {
            //方法执行前...;
            //获取请求参数
            Object request = joinPoint.getArgs()[0];
            //获取该字段
            Field field = request.getClass().getDeclaredField("sign");
            //字段属性可访问
            field.setAccessible(true);
            //加密字段的值
            System.out.println("sign-->" + field.get(request));
            //解密为接口入参对象
            Object decrypt = AesUtil.decrypt(String.valueOf(field.get(request)), request.getClass());
            System.out.println("参数值类型:" + joinPoint.getArgs()[0].getClass().getTypeName());
            System.out.println("解密的值" + decrypt);
            //对象类型的入参直接修改属性即可
        }

        /*-------------------------------------------------*/
        //执行方法,获取返回值
        Object obj = joinPoint.proceed();
        if (obj instanceof Result) {
            Result result = (Result) obj;
            if (!"1".equals(req)){
                Object data1 = result.get("data");
                if (data1 instanceof Page) {
                    Page page = (Page) data1;
                    //若不转换,得到的是page 哈希码。
                    String jsonString = JSONObject.toJSONString(page);
                    // 对返回值进行处理
                    String encrypt = AesUtil.encrypt(jsonString);
                    result.put("data", encrypt);
                }
            }
                return result;
            }
            // 对字段值进行其他操作
        return "";
    }
}

3.加密方式:AES    ECB模式

用了点泛型,将密文转换为入参对象。

@Component
public class AesUtil {

    private static String aesKey;
    @Value("${aesKey}")
    public void setAesKey(String aesKey) {
        AesUtil.aesKey = aesKey;
    }
    /** 加密模式之 ECB,算法/模式/补码方式 */
    private static final String AES_ECB = "AES/ECB/PKCS5Padding";

    public static String encrypt(Object param)  {
        try {
            // 创建密码器
            Cipher cipher = Cipher.getInstance(AES_ECB);
            byte[] byteContent = String.valueOf(param).getBytes("utf-8");
            // 初始化为加密模式的密码器
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(aesKey.getBytes(StandardCharsets.UTF_8), "AES"));
            // 加密
            byte[] result = cipher.doFinal(byteContent);
            //通过Base64转码返回
            return Base64.getEncoder().encodeToString(result);
        } catch (Exception ex) {
            System.out.println("加密失败");
            return null;
        }
    }


    //解密为对应对象
    public static <T> T decrypt(String param , Class<T> clazz) throws InstantiationException, IllegalAccessException {
        //   JSONObject jsonObject = JSONObject.parseObject(param);
        //构建
        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, aesKey.getBytes(StandardCharsets.UTF_8));
        //解密为字符串
        String decryptStr = aes.decryptStr(param, CharsetUtil.CHARSET_UTF_8);
        //报文转对象
//        T t;
//        t = clazz.newInstance();
        T t = JSONObject.parseObject(decryptStr, clazz);
        return t;
    }

    //解密为对应对象集合
    public static <T> List<T> decryptList(String param , Class<T> clazz) throws InstantiationException, IllegalAccessException {
        JSONObject jsonObject = JSONObject.parseObject(param);
        //构建
        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, aesKey.getBytes(StandardCharsets.UTF_8));
        //解密为字符串
        String decryptStr = aes.decryptStr(param, CharsetUtil.CHARSET_UTF_8);
        //报文转对象
        List<T> ts = JSONArray.parseArray(decryptStr, clazz);
        return ts;
    }
}
3.困难点

统一返回对象的data数据中为对象时,得到的不是对象详细信息,而是哈希码。

解决:使用 String jsonString = JSONObject.toJSONString(page); 得到具体数据。

4.测试 

分享一个加解密工具:AES在线加密解密工具 - MKLab在线工具

 1.安卓端

请求头,不加 Req,走切面 。解密参数 。返回值加密。

 解密获得的数据正确

 2.后台

请求头加上 Req = 1 ,入参与返回值正常。

 测试成功

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值