mongodb敏感数据加解密

Posted kuailefangyuan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mongodb敏感数据加解密相关的知识,希望对你有一定的参考价值。

mongodb敏感数据加解密

一、问题背景

公司项目涉及敏感数据存MongoDB库,基于风险要求,敏感数据做SM4国密加密后密文存库,读取时SM4解密为明文。

二、解决方案

项目采用SpringBoot+MongoDB技术框架,使用Spring Data MongoDB的持久化方案。

解决思路:

1、在数据写到mongodb之前,做一层拦截,对明文做SM4加密处理。

2、在mongodb读取数据之后,做一层拦截,对密文做SM4解密处理。

这里介绍下AbstractMongoEventListener类,该类监听Mongodb的增删改查操作,并提供增删改查操作前后的事件,如下图所示:

其中:

  • onBeforeConvert:在 object 被MongoConverter转换为Document之前,在MongoTemplate insertinsertListsave操作中调用。
  • onBeforeSave:在将Document插入或保存在数据库中之前,请在MongoTemplate insertinsertListsave操作中调用。
  • onAfterSave:在**将Document插入或保存在数据库中之后,**在MongoTemplate insertinsertListsave操作中调用。
  • onAfterLoad:从数据库中检索Document后,在MongoTemplate findfindAndRemovefindOnegetCollection方法中调用。
  • onAfterConvert:从数据库中检索到Document后,在MongoTemplate findfindAndRemovefindOnegetCollection方法中调用被转换为 POJO。
  • onAfterDelete : 在数据库删除Document之后调用。
  • onBeforeDelete: 在数据库删除Document之前调用。

这里我们只需继承该上述基类,并覆写其中onBeforeConvert和onAfterConvert方法,即可实现在对象写到mongodb之前做SM4加密,在mongodb读取document转换到对象之后做SM4解密。

三、具体实现

1、首先实现一个SM4Enc字段注解。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SM4Enc 
    SM4EncType encType() default SM4EncType.NAME;

其中加密类型不同,对应的SM4加解密索引也不同,这里定义一个SM4加密索引枚举值:

public enum SM4EncType 
    NAME("A001"),
    PHONE("B001"),
    NONE("NONE");

    private String keyIdx;

    SM4EncType(String keyIdx)
        this.keyIdx = keyIdx;
    

    public String keyIdx()
        return keyIdx;
    

2、实现自定义的mongodb读写时间监听器MongoReadWriteEventListener,监听onBeforeConvertonAfterConvert事件,并对标有@SM4Enc注解的字段进行写前SM4加密,读后SM4解密处理。

@Component
@Slf4j
public class MongoReadWriteEventListener extends AbstractMongoEventListener<Object> 

    @Override
    public void onAfterConvert(AfterConvertEvent<Object> event) 
        if (event.getSource() != null) 
            ReflectionUtils.doWithFields(event.getSource().getClass(), field -> 

                // @SM4Enc注解字段,读库后做SM4解密
                if (field.isAnnotationPresent(SM4Enc.class)) 
                    ReflectionUtils.makeAccessible(field);
                    Object value = field.get(event.getSource());
                    if (value != null) 
                        String ciphertext = (String) value;
                        if (StringUtils.isNotBlank(ciphertext)) 
                            String plainText = SM4ConverterUtil.convertToEntityAttribute(ciphertext);
                            log.info("解密前:,解密后:", ciphertext, plainText);
                            field.set(event.getSource(), plainText);
                        
                    
                
            );
        
    

    @Override
    public void onBeforeConvert(BeforeConvertEvent<Object> event) 
        if (event.getSource() != null) 
            ReflectionUtils.doWithFields(event.getSource().getClass(), field -> 
                // @SM4Enc注解字段,写库前做SM4加密
                if (field.isAnnotationPresent(SM4Enc.class)) 
                    ReflectionUtils.makeAccessible(field);

                    // 获取加密类型
                    SM4Enc sm4Enc = field.getAnnotation(SM4Enc.class);
                    SM4EncType encType = sm4Enc.encType();

                    Object value = field.get(event.getSource());
                    if (value != null) 
                        String plainText = (String) value;
                        String cipherText = SM4ConverterUtil.convertToDatabaseColumn(encType.keyIdx(), plainText);
                        log.info("加密前:,加密后:", plainText, cipherText);
                        field.set(event.getSource(), cipherText);
                    
                
            );
        
    


以上是关于mongodb敏感数据加解密的主要内容,如果未能解决你的问题,请参考以下文章

web.config/app.config敏感数据加/解密的二种方法

使用 Node.js 和 MongoDB 存储密码

常见加解密方法_转

微信小程序crypto-js AES 加解密数据

聊一聊.NET Core结合Nacos实现配置加解密

PHP中常用加解密方式