How can I store and load an encrypted value using custom annotation

末鹿安然 提交于 2021-02-19 04:40:06

问题


I am new to Java custom annotations

I am developing a custom annotation which encrypt and decrypt a string and store it in database using spring and mongodb and for encryption I am using jasypt.

I am not getting the exact procedure to do so.

My code.

Entity

public class Demo {

    @Id
    private Long id;

    private String somethingPublic;

    @EncryptDemo()
    private String somethingPrivate;

   //getter setter

}

custom annotation

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

}

How can I add behavior of encryption to my custom annotation before I store the entity.

Where should I add code for encryption that reflect to my annotation when it called.

I want to develop an annotation same like hibernate.

Any help will be appreciate. Thanks in advance.


回答1:


Basically what you need is to

  1. Create an AbstractMongoEventListener to listen for AfterConvertEvent and BeforeSaveEvent events
  2. Implement org.springframework.util.ReflectionUtils.FieldCallback callbacks to do actions on those events
  3. Register the listener as a Bean in your Spring Data mongodb configuration class

The listener:

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);
    }
}

the Encrypt callback:

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);
    }
}

The Decrypt callback:

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);
    }
}

and finally, register the listener as a bean in your Spring Data mongodb configuration class

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


来源:https://stackoverflow.com/questions/31146221/how-can-i-store-and-load-an-encrypted-value-using-custom-annotation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!