敏感数据加密解密

敏感数据加密解密,第1张

文章目录
  • 敏感数据加密解密
    • 基本概念
    • 元素
    • 对称加密算法
    • 使用AES算法加密解密的一个例子
    • 公司中使用aes算法加密数据库中的身份z信息的一个例子
      • 看一下我们数据库的查询方法
      • 看一下我们的加密方法
        • 加密解密处理器
        • 写一个存储加密解密处理器的容器
        • aes加密密钥
        • EncryptMode加密模式枚举类
        • SqlOperation类
        • 创建加密处理器和解密处理器
        • 使用加密处理器加密输入参数
        • 使用解密处理器解密输出参数
        • 看一下效果
        • 代码

敏感数据加密解密 基本概念

编程的时候,一旦设计到对外访问的接口,或者安全性较高的系统,那么必然会对某些数据进行加密。目前有很多加密算法,比如说MD5,SHA,DES,AES,RSA等等,这些都是常见的加密算法。而我们目前最常用的是AES加密算法。

元素

和密码相关的元素需要掌握四个:

​ 原文:也就做明文,就是被隐藏的真实文字。

​ 加密法:指隐藏明文的法则。

​ 密文:或者叫伪文,指对原文按照加密法处理过后生成的可公开传递的文字。

​ 密钥:在加密法中起决定性的因素,可能是数字,词汇,也可能是一些字母,或者这些东西的组合。

加密结果生成了密文,要想让接受者能够读懂这些密文,那么就要把加密法以及密钥告诉接受者,否者接受者无法对密文解密,也就无法读懂原文。

对称加密算法

对称加密指的就是加密和解密使用同一个密钥,所以说叫做对称加密。对称加密只有一个密钥,作为私钥。具体的算法有很多,但我们常见的是DES,AES等等。

加密的过程我们可以理解为如下:

加密:原文+密钥 = 密文

解密:密文-密钥 = 原文

使用AES算法加密解密的一个例子
public static void main(String[] args) throws Exception {
    /*
        * 此处使用AES-128-ECB加密模式,key需要为16位。
        */
    String cKey = "1234567890123456";
    // 需要加密的字串
    String cSrc = "buxuewushu";
    System.out.println(cSrc);
    // 加密
    String enString = Encrypt(cSrc, cKey);
    System.out.println("加密后的字串是:" + enString);

    // 解密
    String DeString = Decrypt(enString, cKey);
    System.out.println("解密后的字串是:" + DeString);
}
公司中使用aes算法加密数据库中的身份z信息的一个例子 看一下我们数据库的查询方法

我们需要解密一下这句代码的查询结果,所以我们就找到这句代码是代表mapper接口层的哪一个方法,然后给这个方法做个切面处理,如下图:

因此我们给BaseMapper层的这个方法做个切面就行了,如下图:

看一下我们的加密方法 加密解密处理器

首先我们需要用到的是加密,解密处理器,也即是公司自己封装的EncryptHandler加密处理器和DecryptHandler解密处理器,如下图:

写一个存储加密解密处理器的容器

公司前辈又加了一层容器用于存储加密处理器和解密处理器,但这一层容器我觉得没啥必要,后续可以不写,但是为了了解公司业务,这里也记录一下这个容器,如下图:

aes加密密钥

取出我们的aes加密密钥,如下图:

配置文件中的密钥如下图:

EncryptMode加密模式枚举类

这个类也是我们公司自定义的类,如下图:

SqlOperation类

这个类是用来标注我们是数据库读 *** 作还是写 *** 作的,如下图:

创建加密处理器和解密处理器

使用加密处理器加密输入参数

我们加密的是哪个输入参数呢?如下图:

看一下是怎么处理这个参数的,如下图:


那么现在问题来了?如果我们对输出对象里面的属性进行解密,这个我知道原因,是因为我们显示在页面的信息不能是密文,必须要让用户看的懂。但是我对输入参数加密,这是干什么呢啊?有什么用啊?请看下面这个例子:

前提:我们在数据库里存放的手机号都是加密过的手机号,如下图:

但是这样子当用户在前端按照手机号这个条件进行搜索的时候就会出现一个问题,就是用户输入的是手机号码的明文,但是我们数据库中存放的却是数据库的密文,所以二者是不匹配的。那为了解决这个问题,我们就需要把手机号明文转换成手机号密文,然后再去数据库查询。因此我们需要对我们的输入参数进行加密。

使用解密处理器解密输出参数

我们result是我们切面的目标方法返回的结果,如下图:

看一下效果

代码
package com.shunwang.back.aspect;


import com.shunwang.encrypt.core.encrypt.AesEncrypt;
import com.shunwang.encrypt.core.enums.EncryptMode;
import com.shunwang.encrypt.core.enums.SqlOperation;
import com.shunwang.plugin.ibatis.DecryptHandler;
import com.shunwang.plugin.ibatis.EncryptHandler;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Aspect
@Component
public class EncryptAspect {
    private static final Logger log = LoggerFactory.getLogger(EncryptAspect.class);

    private final EncryptHandlerHolder handlerHolder = new EncryptHandlerHolder();
    String key = "basepassport";

    @Value("${mybatis.encrypt.password}")
    String aesKey;

    @Value("${mybatis.encrypt.query-with-cipher-column}")
    boolean queryWithCipherColumn;

    private EncryptMode encryptMode;

    @Around("(execution(* com.shunwang.back.dao.BaseMapper+.find*(..)))" +
            "|| (execution(* com.shunwang.back.dao.BaseMapper+.findCnt(..)))" +
            "|| (execution(* com.shunwang.back.dao.BaseMapper+.get*(..)))")
    public Object interceptQuery(ProceedingJoinPoint joinPoint) throws Throwable {

        EncryptHandler encryptHandler = handlerHolder.getEncryptHandler(key);
        DecryptHandler decryptHandler = handlerHolder.getDecryptHandler(key);

        //1、入参加密
        Object[] args = joinPoint.getArgs();
        if (encryptHandler != null) {
            if (args != null && args.length >= 1) {
                Object arg = args[0];
                if (log.isDebugEnabled()) {
                    log.debug("first arg class:{}", arg == null ? null : arg.getClass());
                }
                long start = System.currentTimeMillis();
                encryptHandler.handle(arg, SqlOperation.QUERY, encryptMode);
                log.debug("time cost query in:" + (System.currentTimeMillis() - start));
            }
        }

        //2、切面执行
        Object result = joinPoint.proceed();

        //3、结果解密
        if (decryptHandler != null) {
            if (result != null) {
                if (log.isDebugEnabled()) {
                    log.debug("返回值类型:{}", result.getClass());
                }
                long start = System.currentTimeMillis();
                decryptHandler.handle(result, SqlOperation.QUERY, encryptMode);
                log.debug("time cost query out:" + (System.currentTimeMillis() - start));
            }
        }

        //4、入参明文还原
        if (encryptMode == EncryptMode.ENCRYPT) {
            //针对入参在后续还被使用的情况,这里把明文写回
            if (decryptHandler != null) {
                if (args != null && args.length >= 1) {
                    Object arg = args[0];
                    if (log.isDebugEnabled()) {
                        log.debug("first arg class:{}", arg == null ? null : arg.getClass());
                    }
                    long start = System.currentTimeMillis();
                    decryptHandler.handle(arg, SqlOperation.QUERY, encryptMode);
                    log.debug("time cost update in:" + (System.currentTimeMillis() - start));
                }
            }
        }
        return result;
    }


    @Around("(execution(* com.shunwang.back.dao.BaseMapper+.save(..)))" +
            "|| (execution(* com.shunwang.back.dao.BaseMapper+.updateById(..)))")
    public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable {
        EncryptHandler encryptHandler = handlerHolder.getEncryptHandler(key);
        DecryptHandler decryptHandler = handlerHolder.getDecryptHandler(key);

        Object[] args = joinPoint.getArgs();
        if (encryptHandler != null) {
            if (args != null && args.length >= 1) {
                Object arg = args[0];
                if (log.isDebugEnabled()) {
                    log.debug("first arg class:{}", arg == null ? null : arg.getClass());
                }
                long start = System.currentTimeMillis();
                encryptHandler.handle(arg, SqlOperation.UPDATE, encryptMode);
                log.debug("time cost update in:" + (System.currentTimeMillis() - start));
            }
        }

        Object result = joinPoint.proceed();

        if (decryptHandler != null) {
            if (result != null) {
                if (log.isDebugEnabled()) {
                    log.debug("返回值类型:{}", result.getClass());
                }
                long start = System.currentTimeMillis();
                decryptHandler.handle(result, SqlOperation.UPDATE, encryptMode);
                log.debug("time cost update out:" + (System.currentTimeMillis() - start));
            }
        }

        if (encryptMode == EncryptMode.ENCRYPT) {
            //针对入参在后续还被使用的情况,这里把明文写回
            if (decryptHandler != null) {
                if (args != null && args.length >= 1) {
                    Object arg = args[0];
                    if (log.isDebugEnabled()) {
                        log.debug("first arg class:{}", arg == null ? null : arg.getClass());
                    }
                    long start = System.currentTimeMillis();
                    decryptHandler.handle(arg, SqlOperation.QUERY, encryptMode);
                    log.debug("time cost update in:" + (System.currentTimeMillis() - start));
                }
            }
        }

        return result;
    }


    @PostConstruct
    public void init() {
        handlerHolder.addEncryptHandler(key, new EncryptHandler(new AesEncrypt(aesKey)));
        handlerHolder.addDecryptHandler(key, new DecryptHandler(new AesEncrypt(aesKey)));
        encryptMode = queryWithCipherColumn ? EncryptMode.ENCRYPT : EncryptMode.PLAIN;
    }
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/791769.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-05
下一篇 2022-05-05

发表评论

登录后才能评论

评论列表(0条)

保存