diff --git a/src/main/java/cokr/xit/foundation/data/paging/EncryptionSupport.java b/src/main/java/cokr/xit/foundation/data/paging/EncryptionSupport.java index fe19f78..4f76dd7 100644 --- a/src/main/java/cokr/xit/foundation/data/paging/EncryptionSupport.java +++ b/src/main/java/cokr/xit/foundation/data/paging/EncryptionSupport.java @@ -4,7 +4,8 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.Collections; import java.util.List; -import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Supplier; import java.util.stream.Stream; import org.apache.ibatis.executor.Executor; @@ -12,48 +13,67 @@ import org.apache.ibatis.executor.resultset.ResultSetHandler; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.plugin.Intercepts; import org.apache.ibatis.plugin.Signature; +import org.apache.ibatis.session.ResultHandler; +import org.apache.ibatis.session.RowBounds; import cokr.xit.foundation.data.ARIA; @Intercepts({ + @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}), @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class}), + @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}), }) public class EncryptionSupport extends MybatisPlugin { private boolean enabled; - private ARIA aria = new ARIA(); + private ARIA aria; - private List decrypted = Collections.emptyList(); private List adaptors = Collections.emptyList(); + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void setEncryptor(ARIA encryptor) { + this.aria = encryptor; + } + + public void setAdaptors(Adaptor... adaptors) { + this.adaptors = List.of(adaptors); + this.adaptors.forEach(adaptor -> adaptor.setARIA(aria)); + } + @Override protected void configure() { String str = properties.getProperty("enabled", ""); - enabled = !"false".equals(str); - - str = properties.getProperty("enc.key"); - aria.setKey(str); - str = properties.getProperty("enc.algorithm"); - if (!isEmpty(str)) - aria.setAlgorithm(str); - - str = properties.getProperty("dec.fields", ""); - if (!isEmpty(str)) - decrypted = List.of(str.split(",")); + setEnabled(!"false".equals(str)); + + if (aria == null) { + aria = new ARIA(); + aria.setKey(properties.getProperty("enc.key")); + str = properties.getProperty("enc.algorithm"); + if (!isEmpty(str)) + aria.setAlgorithm(str); + } str = properties.getProperty("enc.adaptor", ""); if (isEmpty(str)) return; - adaptors = Stream.of(str.split(",")).map(name -> { + List adaptors = Stream.of(str.split(",")).map(name -> { try { Class klass = Class.forName(name); - Adaptor adaptor = (Adaptor)klass.getConstructor().newInstance(); - adaptor.setARIA(aria); - return adaptor; + return (Adaptor)klass.getConstructor().newInstance(); } catch (Exception e) { throw runtimeException(e); } }).toList(); + setAdaptors(adaptors.toArray(new Adaptor[adaptors.size()])); + } + + @Override + protected Object query(Executor executor, MappedStatement mappedStatement, Object obj, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { + encrypt(obj); + return executor.query(mappedStatement, obj, rowBounds, resultHandler); } @Override @@ -71,18 +91,15 @@ public class EncryptionSupport extends MybatisPlugin { } private void decrypt(Object obj) { - if (!enabled || decrypted.isEmpty()) return; + if (!enabled || adaptors.isEmpty()) return; - if (obj instanceof Map) - decrypt((Map)obj); - } - - protected void decrypt(Map map) { - decrypted.forEach(k -> { - if (!map.containsKey(k)) return; + adaptors.forEach(adaptor -> { + if (!adaptor.supports(obj)) return; - Object v = map.get(k); - map.put(k, aria.decrypt((String)v)); + adaptor + .setTarget(obj) + .decrypt() + .clear(); }); } @@ -104,10 +121,12 @@ public class EncryptionSupport extends MybatisPlugin { } private void encrypt(Adaptor adaptor, Object obj) { - if (!adaptor.setTarget(obj)) return; + if (!adaptor.supports(obj)) return; - adaptor.encrypt(); - adaptor.clear(); + adaptor + .setTarget(obj) + .encrypt() + .clear(); } public abstract static class Adaptor { @@ -119,12 +138,32 @@ public class EncryptionSupport extends MybatisPlugin { return this; } - public boolean setTarget(Object obj) { + public Adaptor setTarget(Object obj) { this.obj = obj; - return true; + return this; + } + + public abstract boolean supports(Object obj); + + public abstract boolean isEncrypted(String str); + + public abstract Adaptor encrypt(); + + public abstract Adaptor decrypt(); + + protected void encrypt(Supplier getter, Consumer setter) { + String plain = getter.get(); + if (isEmpty(plain) || isEncrypted(plain)) return; + + setter.accept(aria.encrypt(plain)); } - public abstract void encrypt(); + protected void decrypt(Supplier getter, Consumer setter) { + String encrypted = getter.get(); + if (isEmpty(encrypted) || !isEncrypted(encrypted)) return; + + setter.accept(aria.decrypt(encrypted)); + } public void clear() { obj = null;