문제

We need to encrypt Strings while storing them with JPA and decrypt it when reading it. First of all, we can't use some hibernate config or any other config file because our properties are generic. That means that our properties look like this (simplyfied, we already implemented some handling here):

@Entity
@Table(name = "PROPERTY")
@Access(AccessType.FIELD)
public class Property implements Serializable
{
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "PRO_ID")
    private long id;

    @Version
    @Temporal(value = TemporalType.TIMESTAMP)
    @Column(name = "PRO_VERSION")
    private Date version;

    @Column(name = "PRO_KEY")
    private String key;

    @Transient
    private String value;

    @Column(name = "PRO_ENCRYPTED")
    private boolean encrypted = false;

    public long getId()
    {
        return id;
    }

    public void setId(long id)
    {
        this.id = id;
    }

    public Date getVersion()
    {
        return version;
    }

    public void setVersion(Date version)
    {
        this.version = version;
    }

    public String getKey()
    {
        return key;
    }

    public void setKey(String key)
    {
        this.key = key;
    }

    public String getValue()
    {
        return value;
    }

    public void setValue(String value)
    {
        this.value = value;
    }

    public boolean isEncrypted()
    {
        return encrypted;
    }

    public void setEncrypted(boolean encrypted)
    {
        this.encrypted = encrypted;
    }

    @Access(AccessType.PROPERTY)
    @Column(name = "PRO_VALUE")
    protected String getValueDatabase()
    {
        // TODO: add decryption
        return value;
    }

    protected void setValueDatabase(String value)
    {
        // TODO: add encryption
        this.value = value;
    }
}

(We can distinguish what property has to be encrypted with the isEncrypted() method. This is set to true or false depending on the property). Out Encryptor class (simplified) works with Jasypt:

public final class MyEncrypter
{
    private static final String password = "AHKG@a4SjHH5%j%974";
    private static final StandardPBEStringEncryptor encryptor;

    static 
    {
        encryptor = new StandardPBEStringEncryptor();
        encryptor.setPassword(password);
    }

    public final static String encrypt(String string)
    {
           return encryptor.encrypt(string);
    }

        public final static String decrypt(String encrypted)
        {
            return encryptor.decrypt(encrypted);
        }
}

The encryption/decryption works. Actually our whole persistence handling works. We can save encrypted data. BUT, when we read the encrypted data, we get the following:

javax.persistence.OptimisticLockException: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [at.jit.remind.jee.domain.context.model.Property#10]

The strange thing is, this only happens if and only if Hibernates tries to update the encrypted text. But it DOESN'T happen, when we pseudo encrypt and pseudo decrypt our text. That means we reverse the text, store the reversed text with Hibernate and "decrypted" it when Hibernate tries to update it. So our whole handling works, but what could be the reasons that it doesn't work when we use "real" encryption? Any ideas?

(Again, the en- and decryption itself works. I let run it in different JUnit classes to ensure this.)

도움이 되었습니까?

해결책

We decided to use another encryption because obviously jasypt does something odd to Hibernate. It seems that this encryption/decryption produces somehow a "dirty flag" for Hibernate, so Hibernate tries to update the database entries although the encrytion changes values at the same time. It was not possible to isolate it.

다른 팁

This is because your object is still attached to the hibernate session and its internal state is changed. Try first calling session.evict(object) and then change the text that is to be encrypted.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top