我目前有一个这样的字段注释:
ColumnTransformer(
read="AES_DECRYPT(C_first_name, 'yourkey')",
write="AES_ENCRYPT(?, 'yourkey')")
public String getFirstName() {
return firstName;
}
Run Code Online (Sandbox Code Playgroud)
这适用于Mysql数据库,但我需要这个配置是可选的,因为我们的应用程序可以使用另一个数据库(HsqlDB),具体取决于启动参数.所以我需要的是只有在使用特定的启动参数时才使用ColumnTransformer(并且没有用于HsqlDB的ColumnTransformer,它不能使用"AES_ENCRYPT")
有人可以帮我弄这个吗 ?
小智 5
我有同样的问题,我希望密钥可配置.我在这个项目中找到的唯一解决方案是在运行时更新注释值.是的,我知道这听起来很糟糕,但据我所知,没有别的办法.
实体类:
@Entity
@Table(name = "user")
public class User implements Serializable {
@Column(name = "password")
@ColumnTransformer(read = "AES_DECRYPT(password, '${encryption.key}')", write = "AES_ENCRYPT(?, '${encryption.key}')")
private String password;
}
Run Code Online (Sandbox Code Playgroud)
我实现了将$ {encryption.key}替换为其他值的类(在我的情况下从Spring应用程序上下文加载)
import org.hibernate.annotations.ColumnTransformer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.util.Map;
import javax.annotation.PostConstruct;
@Component(value = "transformerColumnKeyLoader")
public class TransformerColumnKeyLoader {
public static final String KEY_ANNOTATION_PROPERTY = "${encryption.key}";
@Value(value = "${secret.key}")
private String key;
@PostConstruct
public void postConstruct() {
setKey(User.class, "password");
}
private void setKey(Class<?> clazz, String columnName) {
try {
Field field = clazz.getDeclaredField(columnName);
ColumnTransformer columnTransformer = field.getDeclaredAnnotation(ColumnTransformer.class);
updateAnnotationValue(columnTransformer, "read");
updateAnnotationValue(columnTransformer, "write");
} catch (NoSuchFieldException | SecurityException e) {
throw new RuntimeException(
String.format("Encryption key cannot be loaded into %s,%s", clazz.getName(), columnName));
}
}
@SuppressWarnings("unchecked")
private void updateAnnotationValue(Annotation annotation, String annotationProperty) {
Object handler = Proxy.getInvocationHandler(annotation);
Field merberValuesField;
try {
merberValuesField = handler.getClass().getDeclaredField("memberValues");
} catch (NoSuchFieldException | SecurityException e) {
throw new IllegalStateException(e);
}
merberValuesField.setAccessible(true);
Map<String, Object> memberValues;
try {
memberValues = (Map<String, Object>) merberValuesField.get(handler);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
Object oldValue = memberValues.get(annotationProperty);
if (oldValue == null || oldValue.getClass() != String.class) {
throw new IllegalArgumentException(String.format(
"Annotation value should be String. Current value is of type: %s", oldValue.getClass().getName()));
}
String oldValueString = oldValue.toString();
if (!oldValueString.contains(TransformerColumnKeyLoader.KEY_ANNOTATION_PROPERTY)) {
throw new IllegalArgumentException(
String.format("Annotation value should be contain %s. Current value is : %s",
TransformerColumnKeyLoader.KEY_ANNOTATION_PROPERTY, oldValueString));
}
String newValueString = oldValueString.replace(TransformerColumnKeyLoader.KEY_ANNOTATION_PROPERTY, key);
memberValues.put(annotationProperty, newValueString);
}
}
Run Code Online (Sandbox Code Playgroud)
应在创建EntityManager 之前运行此代码.在我的情况下,我使用依赖(对于xml配置或@DependsOn用于java配置).
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" depends-on="transformerColumnKeyLoader"> ... </bean>
Run Code Online (Sandbox Code Playgroud)
hibernate 配置本质上是静态的。它不打算在运行时修改。但如果你认真做的话,是可以做到的。
基本上,构建 SessionFactory 的常用方法是执行以下操作:
AnnotationConfiguration conf = new AnnotationConfiguration().configure();
sessionFactory = conf.buildSessionFactory();
Run Code Online (Sandbox Code Playgroud)
大多数时候,此代码是框架的一部分(例如,使用 Spring,您必须查看 SessionFactoryBean 才能找到它)。因此,要做的第一件事就是识别这部分代码并覆盖执行此操作的框架组件,以便您可以在conf使用该对象之前访问该对象buildSessionFactory()。
然后您必须修改 AnnotationConfiguration 以删除/添加与可选注释相关的数据:
{
...
AnnotationConfiguration conf = new AnnotationConfiguration().configure();
if(FLAG_INDICATING_TO_REMOVE_SOME_ANNOTATION){
manipulateHibernateConfig(conf);
}
sessionFactory = conf.buildSessionFactory();
...
}
private void manipulateHibernateConfig(AnnotationConfiguration conf){
...
//this is the tricky part because lot of fields and setters are either
//final or private so it requires reflection etc...
//you must also be sure that those manipulation won't break the config !
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1348 次 |
| 最近记录: |