欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

使用自定义注解实现加解密及脱敏方式

程序员文章站 2022-03-16 12:48:26
目录自定义注解实现加解密及脱敏定义自定义注解构造aop逻辑测试脱敏逻辑自定义一种字符串的加密与解密自定义注解实现加解密及脱敏定义自定义注解@documented@target({elementtype...

自定义注解实现加解密及脱敏

定义自定义注解

@documented
@target({elementtype.field})
@retention(retentionpolicy.runtime)
@order(ordered.highest_precedence)
public @interface privatedata {
}
@documented
@target({elementtype.method})
@retention(retentionpolicy.runtime)
@order(ordered.highest_precedence)
public @interface privatedatamethod {
}

首先定义两个自定义注解,privatedata和privatedatamethod,分别将@target属性定义为field和method。

构造aop逻辑

申明一个切入点

    @pointcut("@annotation(com.max.base.services.annotation.privatedatamethod)")
    public void annotationpointcut() {
    }

对所有添加@privatedatamethod注解的方法进行切入。

申明通知

@around("annotationpointcut()")
    public object around(proceedingjoinpoint joinpoint) {
        object responseobj = null;
        try {
            object[] request = joinpoint.getargs();
            for (object object : request) {
                if (object instanceof collection) {
                    collection collection = (collection) object;
                    collection.foreach(var -> {
                        try {
                            handleencrypt(var);
                        } catch (illegalaccessexception e) {
                            e.printstacktrace();
                        }
                    });
                } else {
                    handleencrypt(object);
                }
            }
            responseobj = joinpoint.proceed();
            if (responseobj instanceof collection) {
                collection collection = (collection) responseobj;
                collection.foreach(var -> {
                    try {
                        handledecrypt(var);
                    } catch (illegalaccessexception e) {
                        e.printstacktrace();
                    }
                });
            } else {
                handledecrypt(responseobj);
            }
        } catch (throwable throwable) {
            throwable.printstacktrace();
            log.error("securefieldaop 异常{}", throwable);
        }
        return responseobj;
    }

申明aroud通知,对于方法输入输出的对象进行判断,如果是非集合对象则直接进行加解密操作,否则则拆分集合,逐一操作

处理加解密

    /**
     * 处理加密
     * @param requestobj
     */
    private void handleencrypt(object requestobj) throws illegalaccessexception {
        if (objects.isnull(requestobj)) {
            return;
        }
        field[] fields = requestobj.getclass().getdeclaredfields();
        for (field field : fields) {
            boolean hassecurefield = field.isannotationpresent(privatedata.class);
            if (hassecurefield) {
                boolean accessible = field.isaccessible();
                if (!accessible) {
                    field.setaccessible(true);
                }
                string plaintextvalue = (string) field.get(requestobj);
                string encryptvalue = aseutil.encrypt(plaintextvalue, secretkey);
                field.set(requestobj, encryptvalue);
                if (!accessible) {
                    field.setaccessible(false);
                }
            }
        }
    }

通过反射获取对象的field列表,对于拥有@privatedata注解的字段执行**encryptvalue()**方法并用加密后的字符串覆盖原字段。

解密逻辑与加密类似,不做赘述。

测试

标识insert()方法为需要加密的方法

public interface cmtenantmapper {
    int deletebyprimarykey(long id);
    @privatedatamethod
    int insert(cmtenant record);
    int insertselective(cmtenant record);
    cmtenant selectbyprimarykey(long id);
    int updatebyprimarykeyselective(cmtenant record);
    int updatebyprimarykey(cmtenant record);
}

对传入对象中需要加密的字段添加注解

public class cmtenant {
    private long id;
    private string tenantid;
    @privatedata
    private string tenantname;
    private string createby;
    private date createdate;
    private string updateby;
    private date updatedate;
    private string remarks;
    private byte delflag;
//set get...

调用insert方法查看数据保存结果

传入对象

{
  "createby": "可乐可不乐",
  "delflag": "notdelete",
  "remarks": "测试加密",
  "tenantid": "996",
  "tenantname": "椅子团队出品",
  "updateby": "可乐可不乐"
}

数据库保存对象

解密测试不做注释,大家自行尝试

脱敏逻辑

脱敏逻辑与加解密基本一致,需要注意的一点是脱敏的注解需要添加type类型

@documented
@target({elementtype.field})
@retention(retentionpolicy.runtime)
@order(ordered.highest_precedence)
public @interface maskingfield {
    maskingtypeenum type();
}

在maskingtypeenum中定义脱敏的分类

public enum maskingtypeenum {
    /*身份证号码*/
    id_card,
    /*手机号码*/
    phone,
    /*地址*/
    address,
    /*姓名*/
    name
}

在使用是maskingtypeenum时标识字段的类型

   @maskingfield(type = maskingtypeenum.name)
    private string cpname;

自定义一种字符串的加密与解密

package com.hanqi.lianxi;
package com.hanqi.lianxi;
import java.util.scanner;
public class jiamiqi
{
    public static void main(string[] args)
    {
        //输入解密前的内容
    scanner sc = new scanner(system.in);
    system.out.println("请输入需要解码的信件内容");
    string tex = sc.nextline();
        //用替换的方式实现解密
    system.out.print("解密后的内容为:"+tex.replaceall("a", "c").replaceall("b", "d").replaceall("c", "e").replaceall("d", "f").replaceall("e", "g").replaceall("f", "h").replaceall("g", "i").replaceall("h", "j").replaceall("i", "k").replaceall("j", "l").replaceall("k", "m").replaceall("l", "n").replaceall("m", "o").replaceall("n", "p").replaceall("o", "q").replaceall("p", "r").replaceall("q", "s").replaceall("r", "t").replaceall("s", "u").replaceall("t", "v").replaceall("u", "w").replaceall("v", "x").replaceall("w", "y").replaceall("x", "z").replaceall("y", "a").replaceall("z", "b"));    
    }
}

使用自定义注解实现加解密及脱敏方式

使用自定义注解实现加解密及脱敏方式

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。