7

現在、次のように注釈が付けられたフィールドがあります。

ColumnTransformer(
          read="AES_DECRYPT(C_first_name, 'yourkey')",
          write="AES_ENCRYPT(?, 'yourkey')")
public String getFirstName() {
   return firstName;
}

これは Mysql データベースで適切に動作していますが、アプリケーションが開始パラメータに応じて別のデータベース (HsqlDB) を使用できるため、この構成をオプションにする必要があります。したがって、特定の開始パラメーターが使用されている場合にのみ ColumnTransformer を使用する方法が必要です (「AES_ENCRYPT」を使用できない HsqlDB 用の ColumnTransformer はありません)。

誰かがこれで私を助けることができますか?

4

6 に答える 6

6

私は同じ問題を抱えていました。キーを設定可能にしたいのです。この項目について私が見つけた唯一の解決策は、実行時に注釈値を更新することです。はい、これはひどいことだと思いますが、私の知る限り、他に方法はありません。

エンティティ クラス:

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

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

このコードは、EntityManager を作成する前に実行する必要があります。私の場合、依存関係を使用しました(xml構成の場合、またはJava構成の@DependsOn)。

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" depends-on="transformerColumnKeyLoader"> ... </bean>
于 2016-11-18T10:38:48.827 に答える
0

user3035947 の回答に基づく:

@Component
public class RemoveAesFunction {



    @PostConstruct
    public void postConstruct() {
        setKey(MyEntity.class);
    }

    private void setKey(Class<?> clazz) {
        try {
            Field field = clazz.getDeclaredField("firstName");

            ColumnTransformer columnTransformer = field.getDeclaredAnnotation(ColumnTransformer.class);
            updateAnnotationValue(columnTransformer, "read","");
            updateAnnotationValue(columnTransformer, "write","?");
        } catch (NoSuchFieldException | SecurityException e) {
            throw new RuntimeException();
        }
    }

    @SuppressWarnings("unchecked")
    private void updateAnnotationValue(Annotation annotation, String annotationProperty,String value) {
        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);
        }

        memberValues.put(annotationProperty, value);
    }
}
于 2016-11-23T11:29:23.517 に答える