diff --git a/continew-starter-core/src/main/java/top/continew/starter/core/constant/StringConstants.java b/continew-starter-core/src/main/java/top/continew/starter/core/constant/StringConstants.java index ff304c7d..8247d960 100644 --- a/continew-starter-core/src/main/java/top/continew/starter/core/constant/StringConstants.java +++ b/continew-starter-core/src/main/java/top/continew/starter/core/constant/StringConstants.java @@ -272,6 +272,11 @@ public class StringConstants { */ public static final String ROUND_BRACKET_END = ")"; + /** + * 等号(=) + */ + public static final String EQUALS = "="; + /** * 路径模式 */ diff --git a/continew-starter-data/continew-starter-data-mp/src/main/java/top/continew/starter/data/mp/autoconfigure/MybatisPlusAutoConfiguration.java b/continew-starter-data/continew-starter-data-mp/src/main/java/top/continew/starter/data/mp/autoconfigure/MybatisPlusAutoConfiguration.java index 5b81789a..72f89b18 100644 --- a/continew-starter-data/continew-starter-data-mp/src/main/java/top/continew/starter/data/mp/autoconfigure/MybatisPlusAutoConfiguration.java +++ b/continew-starter-data/continew-starter-data-mp/src/main/java/top/continew/starter/data/mp/autoconfigure/MybatisPlusAutoConfiguration.java @@ -22,6 +22,7 @@ import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler; import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import jakarta.annotation.PostConstruct; import org.mybatis.spring.annotation.MapperScan; @@ -43,6 +44,8 @@ import top.continew.starter.data.mp.datapermission.DataPermissionHandlerImpl; import top.continew.starter.data.mp.handler.MybatisBaseEnumTypeHandler; +import java.util.Map; + /** * MyBatis Plus 自动配置 * @@ -76,6 +79,11 @@ public MybatisPlusPropertiesCustomizer mybatisPlusPropertiesCustomizer() { @ConditionalOnMissingBean public MybatisPlusInterceptor mybatisPlusInterceptor(MyBatisPlusExtensionProperties properties) { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 其他拦截器 + Map innerInterceptors = SpringUtil.getBeansOfType(InnerInterceptor.class); + if (!innerInterceptors.isEmpty()) { + innerInterceptors.values().forEach(interceptor::addInnerInterceptor); + } // 数据权限插件 MyBatisPlusExtensionProperties.DataPermissionProperties dataPermissionProperties = properties .getDataPermission(); diff --git a/continew-starter-dependencies/pom.xml b/continew-starter-dependencies/pom.xml index 4fa7411a..283f898c 100644 --- a/continew-starter-dependencies/pom.xml +++ b/continew-starter-dependencies/pom.xml @@ -137,6 +137,11 @@ mybatis-plus-core ${mybatis-plus.version} + + com.baomidou + mybatis-plus-extension + ${mybatis-plus.version} + diff --git a/continew-starter-security/continew-starter-security-crypto/pom.xml b/continew-starter-security/continew-starter-security-crypto/pom.xml index b08549a4..cf82f2d7 100644 --- a/continew-starter-security/continew-starter-security-crypto/pom.xml +++ b/continew-starter-security/continew-starter-security-crypto/pom.xml @@ -22,7 +22,7 @@ com.baomidou - mybatis-plus-core + mybatis-plus-extension \ No newline at end of file diff --git a/continew-starter-security/continew-starter-security-crypto/src/main/java/top/continew/starter/security/crypto/autoconfigure/CryptoAutoConfiguration.java b/continew-starter-security/continew-starter-security-crypto/src/main/java/top/continew/starter/security/crypto/autoconfigure/CryptoAutoConfiguration.java index 4a63c888..66d3f47c 100644 --- a/continew-starter-security/continew-starter-security-crypto/src/main/java/top/continew/starter/security/crypto/autoconfigure/CryptoAutoConfiguration.java +++ b/continew-starter-security/continew-starter-security-crypto/src/main/java/top/continew/starter/security/crypto/autoconfigure/CryptoAutoConfiguration.java @@ -50,7 +50,7 @@ public CryptoAutoConfiguration(CryptoProperties properties) { * MyBatis 加密拦截器配置 */ @Bean - @ConditionalOnMissingBean(MyBatisEncryptInterceptor.class) + @ConditionalOnMissingBean public MyBatisEncryptInterceptor myBatisEncryptInterceptor() { return new MyBatisEncryptInterceptor(properties); } diff --git a/continew-starter-security/continew-starter-security-crypto/src/main/java/top/continew/starter/security/crypto/core/AbstractMyBatisInterceptor.java b/continew-starter-security/continew-starter-security-crypto/src/main/java/top/continew/starter/security/crypto/core/AbstractMyBatisInterceptor.java index d30100ba..aeaeea4c 100644 --- a/continew-starter-security/continew-starter-security-crypto/src/main/java/top/continew/starter/security/crypto/core/AbstractMyBatisInterceptor.java +++ b/continew-starter-security/continew-starter-security-crypto/src/main/java/top/continew/starter/security/crypto/core/AbstractMyBatisInterceptor.java @@ -16,27 +16,14 @@ package top.continew.starter.security.crypto.core; -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.util.ReflectUtil; import cn.hutool.extra.spring.SpringUtil; -import com.baomidou.mybatisplus.core.toolkit.Constants; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.mapping.MappedStatement; -import org.apache.ibatis.mapping.SqlCommandType; -import org.apache.ibatis.plugin.Interceptor; -import top.continew.starter.core.constant.StringConstants; -import top.continew.starter.core.exception.BusinessException; import top.continew.starter.security.crypto.annotation.FieldEncrypt; import top.continew.starter.security.crypto.encryptor.IEncryptor; import top.continew.starter.security.crypto.enums.Algorithm; import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Parameter; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Stream; /** * 字段解密拦截器 @@ -44,9 +31,7 @@ * @author Charles7c * @since 1.4.0 */ -public abstract class AbstractMyBatisInterceptor implements Interceptor { - - private static final Map> ENCRYPT_PARAM_CACHE = new ConcurrentHashMap<>(); +public abstract class AbstractMyBatisInterceptor { /** * 获取所有字符串类型、需要加/解密的、有值字段 @@ -58,10 +43,19 @@ public List getEncryptFields(Object obj) { if (null == obj) { return Collections.emptyList(); } - return Arrays.stream(ReflectUtil.getFields(obj.getClass())) + return this.getEncryptFields(obj.getClass()); + } + + /** + * 获取所有字符串类型、需要加/解密的、有值字段 + * + * @param clazz 类型对象 + * @return 字段列表 + */ + public List getEncryptFields(Class clazz) { + return Arrays.stream(ReflectUtil.getFields(clazz)) .filter(field -> String.class.equals(field.getType())) .filter(field -> null != field.getAnnotation(FieldEncrypt.class)) - .filter(field -> null != ReflectUtil.getFieldValue(obj, field)) .toList(); } @@ -81,115 +75,4 @@ public IEncryptor getEncryptor(FieldEncrypt fieldEncrypt) { // 使用自定义加/解密处理器 return SpringUtil.getBean(encryptorClass); } - - /** - * 获取加密参数 - * - * @param mappedStatement 映射语句 - * @return 加密参数 - */ - public Map getEncryptParams(MappedStatement mappedStatement) { - return getEncryptParams(mappedStatement, null); - } - - /** - * 获取加密参数 - * - * @param mappedStatement 映射语句 - * @param parameterCount 参数数量 - * @return 加密参数 - */ - public Map getEncryptParams(MappedStatement mappedStatement, Integer parameterCount) { - String mappedStatementId = mappedStatement.getId(); - SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType(); - if (SqlCommandType.UPDATE != sqlCommandType) { - return ENCRYPT_PARAM_CACHE.computeIfAbsent(mappedStatementId, key -> this - .getEncryptParams(mappedStatementId, parameterCount)); - } else { - return this.getEncryptParams(mappedStatementId, parameterCount); - } - } - - /** - * 获取参数名称 - * - * @param parameter 参数 - * @return 参数名称 - */ - public String getParameterName(Parameter parameter) { - Param param = parameter.getAnnotation(Param.class); - return null != param ? param.value() : parameter.getName(); - } - - /** - * 获取加密参数列表 - * - * @param mappedStatementId 映射语句 ID - * @param parameterCount 参数数量 - * @return 加密参数列表 - */ - private Map getEncryptParams(String mappedStatementId, Integer parameterCount) { - Method method = this.getMethod(mappedStatementId, parameterCount); - if (method == null) { - return Collections.emptyMap(); - } - return this.getEncryptParams(method); - } - - /** - * 获取映射方法 - * - * @param mappedStatementId 映射语句 ID - * @param parameterCount 参数数量 - * @return 映射方法 - */ - private Method getMethod(String mappedStatementId, Integer parameterCount) { - try { - String className = CharSequenceUtil.subBefore(mappedStatementId, StringConstants.DOT, true); - String wrapperMethodName = CharSequenceUtil.subAfter(mappedStatementId, StringConstants.DOT, true); - String methodName = Stream.of("_mpCount", "_COUNT") - .filter(wrapperMethodName::endsWith) - .findFirst() - .map(suffix -> wrapperMethodName.substring(0, wrapperMethodName.length() - suffix.length())) - .orElse(wrapperMethodName); - // 获取真实方法 - Optional methodOptional = Arrays.stream(ReflectUtil.getMethods(Class.forName(className), m -> { - if (parameterCount != null) { - return Objects.equals(m.getName(), methodName) && m.getParameterCount() == parameterCount; - } - return Objects.equals(m.getName(), methodName); - })).findFirst(); - return methodOptional.orElse(null); - } catch (ClassNotFoundException e) { - throw new BusinessException(e.getMessage()); - } - } - - /** - * 获取加密参数列表 - * - * @param method 方法 - * @return 加密参数列表 - */ - private Map getEncryptParams(Method method) { - // 获取方法中的加密参数 - Map map = MapUtil.newHashMap(); - Parameter[] parameterArr = method.getParameters(); - for (int i = 0; i < parameterArr.length; i++) { - Parameter parameter = parameterArr[i]; - String parameterName = this.getParameterName(parameter); - FieldEncrypt fieldEncrypt = parameter.getAnnotation(FieldEncrypt.class); - if (null != fieldEncrypt) { - map.put(parameterName, fieldEncrypt); - if (String.class.equals(parameter.getType())) { - map.put("param" + (i + 1), fieldEncrypt); - } - } else if (parameterName.startsWith(Constants.ENTITY)) { - map.put(parameterName, null); - } else if (parameterName.startsWith(Constants.WRAPPER)) { - map.put(parameterName, null); - } - } - return map; - } } \ No newline at end of file diff --git a/continew-starter-security/continew-starter-security-crypto/src/main/java/top/continew/starter/security/crypto/core/MyBatisDecryptInterceptor.java b/continew-starter-security/continew-starter-security-crypto/src/main/java/top/continew/starter/security/crypto/core/MyBatisDecryptInterceptor.java index 21e5a35f..0dec638f 100644 --- a/continew-starter-security/continew-starter-security-crypto/src/main/java/top/continew/starter/security/crypto/core/MyBatisDecryptInterceptor.java +++ b/continew-starter-security/continew-starter-security-crypto/src/main/java/top/continew/starter/security/crypto/core/MyBatisDecryptInterceptor.java @@ -36,7 +36,7 @@ * @since 1.4.0 */ @Intercepts({@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})}) -public class MyBatisDecryptInterceptor extends AbstractMyBatisInterceptor { +public class MyBatisDecryptInterceptor extends AbstractMyBatisInterceptor implements Interceptor { private CryptoProperties properties; @@ -65,6 +65,9 @@ public Object intercept(Invocation invocation) throws Throwable { for (Field field : fieldList) { IEncryptor encryptor = super.getEncryptor(field.getAnnotation(FieldEncrypt.class)); Object fieldValue = ReflectUtil.getFieldValue(result, field); + if (null == fieldValue) { + continue; + } // 优先获取自定义对称加密算法密钥,获取不到时再获取全局配置 String password = ObjectUtil.defaultIfBlank(field.getAnnotation(FieldEncrypt.class) .password(), properties.getPassword()); diff --git a/continew-starter-security/continew-starter-security-crypto/src/main/java/top/continew/starter/security/crypto/core/MyBatisEncryptInterceptor.java b/continew-starter-security/continew-starter-security-crypto/src/main/java/top/continew/starter/security/crypto/core/MyBatisEncryptInterceptor.java index 88b7eac1..36a1640d 100644 --- a/continew-starter-security/continew-starter-security-crypto/src/main/java/top/continew/starter/security/crypto/core/MyBatisEncryptInterceptor.java +++ b/continew-starter-security/continew-starter-security-crypto/src/main/java/top/continew/starter/security/crypto/core/MyBatisEncryptInterceptor.java @@ -20,30 +20,24 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ReflectUtil; import com.baomidou.mybatisplus.core.conditions.AbstractWrapper; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.metadata.TableFieldInfo; -import com.baomidou.mybatisplus.core.metadata.TableInfo; -import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.baomidou.mybatisplus.core.toolkit.Constants; -import org.apache.ibatis.cache.CacheKey; +import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; -import org.apache.ibatis.mapping.SqlCommandType; -import org.apache.ibatis.plugin.*; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; -import org.apache.ibatis.type.SimpleTypeRegistry; import top.continew.starter.core.constant.StringConstants; +import top.continew.starter.core.exception.BaseException; import top.continew.starter.security.crypto.annotation.FieldEncrypt; import top.continew.starter.security.crypto.autoconfigure.CryptoProperties; import top.continew.starter.security.crypto.encryptor.IEncryptor; import java.lang.reflect.Field; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; +import java.sql.SQLException; import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * 字段加密拦截器 @@ -51,145 +45,142 @@ * @author Charles7c * @since 1.4.0 */ -@Intercepts({@Signature(method = "update", type = Executor.class, args = {MappedStatement.class, Object.class}), - @Signature(method = "query", type = Executor.class, args = {MappedStatement.class, Object.class, RowBounds.class, - ResultHandler.class, CacheKey.class, BoundSql.class}), - @Signature(method = "query", type = Executor.class, args = {MappedStatement.class, Object.class, RowBounds.class, - ResultHandler.class})}) -public class MyBatisEncryptInterceptor extends AbstractMyBatisInterceptor { +public class MyBatisEncryptInterceptor extends AbstractMyBatisInterceptor implements InnerInterceptor { - private CryptoProperties properties; + private static final Pattern PARAM_PAIRS_PATTERN = Pattern + .compile("#\\{ew\\.paramNameValuePairs\\.(" + Constants.WRAPPER_PARAM + "\\d+)\\}"); + private final CryptoProperties properties; public MyBatisEncryptInterceptor(CryptoProperties properties) { this.properties = properties; } - public MyBatisEncryptInterceptor() { + @Override + public void beforeQuery(Executor executor, + MappedStatement mappedStatement, + Object parameterObject, + RowBounds rowBounds, + ResultHandler resultHandler, + BoundSql boundSql) { + if (null == parameterObject) { + return; + } + if (parameterObject instanceof Map parameterMap) { + Set set = new HashSet<>(parameterMap.values()); + for (Object parameter : set) { + if (parameter instanceof AbstractWrapper || parameter instanceof String) { + continue; + } + this.encryptEntity(super.getEncryptFields(parameter), parameter); + } + } } @Override - public Object intercept(Invocation invocation) throws Throwable { - Object[] args = invocation.getArgs(); - MappedStatement mappedStatement = (MappedStatement)args[0]; - Object parameter = args[1]; - if (!this.isEncryptRequired(parameter, mappedStatement.getSqlCommandType())) { - return invocation.proceed(); + public void beforeUpdate(Executor executor, + MappedStatement mappedStatement, + Object parameterObject) throws SQLException { + if (null == parameterObject) { + return; } - // 使用 @Param 注解的场景 - if (parameter instanceof HashMap parameterMap) { + if (parameterObject instanceof Map parameterMap) { + // 带别名方法(使用 @Param 注解的场景) this.encryptMap(parameterMap, mappedStatement); } else { - this.doEncrypt(this.getEncryptFields(parameter), parameter); + // 无别名方法(例如:MP insert 等方法) + this.encryptEntity(super.getEncryptFields(parameterObject), parameterObject); } - return invocation.proceed(); } /** - * 是否需要加密处理 + * 加密 Map 类型数据(使用 @Param 注解的场景) * - * @param parameter 参数 - * @param sqlCommandType SQL 类型 - * @return true:是;false:否 + * @param parameterMap 参数 + * @param mappedStatement 映射语句 */ - private boolean isEncryptRequired(Object parameter, SqlCommandType sqlCommandType) { - if (ObjectUtil.isEmpty(parameter)) { - return false; + private void encryptMap(Map parameterMap, MappedStatement mappedStatement) { + Object parameter; + // 别名带有 et(针对 MP 的 updateById、update 等方法) + if (parameterMap.containsKey(Constants.ENTITY) && null != (parameter = parameterMap.get(Constants.ENTITY))) { + this.encryptEntity(super.getEncryptFields(parameter), parameter); } - if (!(SqlCommandType.UPDATE == sqlCommandType || SqlCommandType.INSERT == sqlCommandType || SqlCommandType.SELECT == sqlCommandType)) { - return false; + // 别名带有 ew(针对 MP 的 UpdateWrapper、LambdaUpdateWrapper 等参数) + if (parameterMap.containsKey(Constants.WRAPPER) && null != (parameter = parameterMap.get(Constants.WRAPPER))) { + this.encryptWrapper(parameter, mappedStatement); } - return !SimpleTypeRegistry.isSimpleType(parameter.getClass()); } /** - * 加密 Map 类型数据(使用 @Param 注解的场景) + * 处理 Wrapper 类型参数加密(针对 MP 的 UpdateWrapper、LambdaUpdateWrapper 等参数) * - * @param parameterMap 参数 + * @param parameter Wrapper 参数 * @param mappedStatement 映射语句 - * @throws Exception / + * @since 2.1.1 + * @author cary + * @author wangshaopeng@talkweb.com.cn(基于Mybatis-Plus拦截器实现MySQL数据加解密) */ - private void encryptMap(HashMap parameterMap, MappedStatement mappedStatement) throws Exception { - Map encryptParamMap = super.getEncryptParams(mappedStatement); - if (encryptParamMap.isEmpty() && !parameterMap.isEmpty()) { - encryptParamMap = super.getEncryptParams(mappedStatement, parameterMap.size() / 2); - } - for (Map.Entry encryptParamEntry : encryptParamMap.entrySet()) { - String parameterName = encryptParamEntry.getKey(); - if (parameterName.startsWith(Constants.ENTITY)) { - // 兼容 MyBatis Plus 封装的 update 相关方法,updateById、update - Object entity = parameterMap.getOrDefault(parameterName, null); - this.doEncrypt(this.getEncryptFields(entity), entity); - } else if (parameterName.startsWith(Constants.WRAPPER)) { - // 处理参数为 Wrapper 的情况 - Wrapper wrapper = (Wrapper)parameterMap.getOrDefault(parameterName, null); - this.doEncrypt(wrapper, mappedStatement); - } else { - FieldEncrypt fieldEncrypt = encryptParamEntry.getValue(); - parameterMap.put(parameterName, this.doEncrypt(parameterMap.get(parameterName), fieldEncrypt)); + private void encryptWrapper(Object parameter, MappedStatement mappedStatement) { + if (parameter instanceof AbstractWrapper updateWrapper) { + String sqlSet = updateWrapper.getSqlSet(); + if (CharSequenceUtil.isBlank(sqlSet)) { + return; + } + // 将 name=#{ew.paramNameValuePairs.xxx},age=#{ew.paramNameValuePairs.xxx} 切出来 + String[] elArr = sqlSet.split(StringConstants.COMMA); + Map propMap = new HashMap<>(elArr.length); + Arrays.stream(elArr).forEach(el -> { + String[] elPart = el.split(StringConstants.EQUALS); + propMap.put(elPart[0], elPart[1]); + }); + // 获取加密字段 + Class entityClass = mappedStatement.getParameterMap().getType(); + List encryptFieldList = super.getEncryptFields(entityClass); + for (Field field : encryptFieldList) { + FieldEncrypt fieldEncrypt = field.getAnnotation(FieldEncrypt.class); + String el = propMap.get(field.getName()); + if (CharSequenceUtil.isBlank(el)) { + continue; + } + Matcher matcher = PARAM_PAIRS_PATTERN.matcher(el); + if (matcher.matches()) { + String valueKey = matcher.group(1); + Object value = updateWrapper.getParamNameValuePairs().get(valueKey); + Object ciphertext; + try { + ciphertext = this.doEncrypt(value, fieldEncrypt); + } catch (Exception e) { + throw new BaseException(e); + } + updateWrapper.getParamNameValuePairs().put(valueKey, ciphertext); + } } } } /** - * 处理加密 + * 处理实体加密 * * @param fieldList 加密字段列表 * @param entity 实体 - * @throws Exception / */ - private void doEncrypt(List fieldList, Object entity) throws Exception { + private void encryptEntity(List fieldList, Object entity) { for (Field field : fieldList) { IEncryptor encryptor = super.getEncryptor(field.getAnnotation(FieldEncrypt.class)); Object fieldValue = ReflectUtil.getFieldValue(entity, field); + if (null == fieldValue) { + continue; + } // 优先获取自定义对称加密算法密钥,获取不到时再获取全局配置 String password = ObjectUtil.defaultIfBlank(field.getAnnotation(FieldEncrypt.class).password(), properties .getPassword()); - String ciphertext = encryptor.encrypt(fieldValue.toString(), password, properties.getPublicKey()); - ReflectUtil.setFieldValue(entity, field, ciphertext); - } - } - - /** - * 处理 Wrapper 加密 - * - * @param wrapper Wrapper 对象 - * @param mappedStatement 映射语句 - * @throws Exception / - */ - private void doEncrypt(Wrapper wrapper, MappedStatement mappedStatement) throws Exception { - if (wrapper instanceof AbstractWrapper abstractWrapper) { - String sqlSet = abstractWrapper.getSqlSet(); - if (CharSequenceUtil.isEmpty(sqlSet)) { - return; - } - String className = CharSequenceUtil.subBefore(mappedStatement.getId(), StringConstants.DOT, true); - Class mapperClass = Class.forName(className); - Optional baseMapperGenerics = getEntityTypeByMapperClass(mapperClass, Optional.empty()); - // 获取不到泛型对象 则不进行下面的逻辑 - if (baseMapperGenerics.isEmpty()) { - return; - } - TableInfo tableInfo = TableInfoHelper.getTableInfo(baseMapperGenerics.get()); - List fieldList = tableInfo.getFieldList(); - // 将 name=#{ew.paramNameValuePairs.xxx},age=#{ew.paramNameValuePairs.xxx} 切出来 - for (String sqlFragment : sqlSet.split(Constants.COMMA)) { - String columnName = sqlFragment.split(Constants.EQUALS)[0]; - // 截取其中的 xxx 字符,例如:#{ew.paramNameValuePairs.xxx} - String paramNameVal = sqlFragment.split(Constants.EQUALS)[1].substring(25, sqlFragment - .split(Constants.EQUALS)[1].length() - 1); - Optional fieldInfo = fieldList.stream() - .filter(f -> f.getColumn().equals(columnName)) - .findAny(); - if (fieldInfo.isPresent()) { - TableFieldInfo tableFieldInfo = fieldInfo.get(); - FieldEncrypt fieldEncrypt = tableFieldInfo.getField().getAnnotation(FieldEncrypt.class); - if (fieldEncrypt != null) { - Map paramNameValuePairs = abstractWrapper.getParamNameValuePairs(); - paramNameValuePairs.put(paramNameVal, this.doEncrypt(paramNameValuePairs - .get(paramNameVal), fieldEncrypt)); - } - } + String ciphertext; + try { + ciphertext = encryptor.encrypt(fieldValue.toString(), password, properties.getPublicKey()); + } catch (Exception e) { + throw new BaseException(e); } + ReflectUtil.setFieldValue(entity, field, ciphertext); } } @@ -209,40 +200,4 @@ private Object doEncrypt(Object parameterValue, FieldEncrypt fieldEncrypt) throw String password = ObjectUtil.defaultIfBlank(fieldEncrypt.password(), properties.getPassword()); return encryptor.encrypt(parameterValue.toString(), password, properties.getPublicKey()); } - - /** - * 从 Mapper 获取泛型 - * - * @param mapperClass Mapper class - * @param tempResult 临时存储的泛型对象 - * @return 泛型 - */ - private static Optional getEntityTypeByMapperClass(Class mapperClass, Optional tempResult) { - Type[] genericInterfaces = mapperClass.getGenericInterfaces(); - Optional result = tempResult; - for (Type genericInterface : genericInterfaces) { - if (genericInterface instanceof ParameterizedType parameterizedType) { - Type rawType = parameterizedType.getRawType(); - Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); - // 如果匹配上 BaseMapper 且泛型参数是 Class 类型,则直接返回 - if (rawType.equals(BaseMapper.class)) { - return actualTypeArguments[0] instanceof Class - ? Optional.of((Class)actualTypeArguments[0]) - : result; - } else if (rawType instanceof Class interfaceClass) { - // 如果泛型参数是 Class 类型,则传递给递归调用 - if (actualTypeArguments[0] instanceof Class tempResultClass) { - result = Optional.of(tempResultClass); - } - // 递归调用,继续查找 - Optional innerResult = getEntityTypeByMapperClass(interfaceClass, result); - if (innerResult.isPresent()) { - return innerResult; - } - } - } - } - // 如果没有找到,返回传递进来的 tempResult - return Optional.empty(); - } }