【问题标题】:How can I store and load an encrypted value using custom annotation如何使用自定义注释存储和加载加密值
【发布时间】:2015-06-30 18:54:38
【问题描述】:

我是 Java 自定义注解的新手

我正在开发一个自定义注释来加密和解密字符串 并使用 spring 和 mongodb 将其存储在数据库中,我使用 jasypt 进行加密。

我没有得到这样做的确切程序。

我的代码。

实体

public class Demo {

    @Id
    private Long id;

    private String somethingPublic;

    @EncryptDemo()
    private String somethingPrivate;

   //getter setter

}

自定义注释

@Target({ ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptDemo {

}

如何在存储实体之前向自定义注释添加加密行为。

我应该在哪里添加在调用时反映到我的注释的加密代码。

我想开发一个和hibernate一样的注解。

任何帮助将不胜感激。提前致谢。

【问题讨论】:

标签: java spring mongodb hibernate annotations


【解决方案1】:

基本上你需要的是

  1. 创建一个AbstractMongoEventListener 来监听AfterConvertEventBeforeSaveEvent 事件
  2. 实现 org.springframework.util.ReflectionUtils.FieldCallback 回调以对这些事件执行操作
  3. 在 Spring Data mongodb 配置类中将监听器注册为 Bean

听者:

public class EncryptionMongoEventListener extends AbstractMongoEventListener<Object> {
    @Override
    public void onBeforeSave(BeforeSaveEvent<Object> event) {
        Object source = event.getSource();
        DBObject dbObject = event.getDBObject();
        ReflectionUtils.doWithFields(source.getClass(), 
            new EncryptCallback(source, dbObject),
            ReflectionUtils.COPYABLE_FIELDS);
    }
    @Override
    public void onAfterConvert(AfterConvertEvent<Object> event) {
        Object source = event.getSource();
        ReflectionUtils.doWithFields(source.getClass(), 
            new DecryptCallback(source),
            ReflectionUtils.COPYABLE_FIELDS);
    }
}

加密回调:

class EncryptCallback implements FieldCallback {
    private final Object source;
    private final DBObject dbObject;

    public EncryptCallback(final Object source, final DBObject dbObject) {
        this.source = source;
        this.dbObject = dbObject;
    }

    @Override
    public void doWith(Field field) 
        throws IllegalArgumentException, IllegalAccessException {
        if (!field.isAnnotationPresent(/* your annotation */.class)) {
            return;
        }
        ReflectionUtils.makeAccessible(field);
        String plainText = (String) ReflectionUtils.getField(field, source);
        String encryptedValue = /* your encryption of plainText */;
        // update the value in DBObject before it is saved to mongodb
        dbObject.put(field.getName(), encryptedValue);
    }
}

解密回调:

class DecryptCallback implements FieldCallback {
    private final Object source;

    public DecryptCallback(Object source) {
        this.source = source;
    }

    @Override
    public void doWith(Field field) 
        throws IllegalArgumentException, IllegalAccessException {
        if (!field.isAnnotationPresent(/* your annotation */.class)) {
            return;
        }
        ReflectionUtils.makeAccessible(field);
        String fieldValue = (String) ReflectionUtils.getField(field, source);
        String decryptedValue = /* your decryption of fieldValue */;
        // set the decrypted value in source Object
        ReflectionUtils.setField(field, source, decryptedValue);
    }
}

最后,将监听器注册为 Spring Data mongodb 配置类中的 bean

@Bean
public EncryptionMongoEventListener encryptionMongoEventListener() {
    return new EncryptionMongoEventListener();
}

【讨论】:

  • 如何处理日期字段等不同数据类型的字段??
猜你喜欢
  • 2018-05-07
  • 1970-01-01
  • 1970-01-01
  • 2016-10-05
  • 1970-01-01
  • 2021-06-22
  • 1970-01-01
  • 2017-11-06
  • 2023-03-27
相关资源
最近更新 更多