mirror of
https://github.com/continew-org/continew-starter.git
synced 2025-09-10 20:57:18 +08:00
fix(security/crypto): 修复 updateById 修改未正确加密的问题
This commit is contained in:
@@ -22,7 +22,9 @@ import cn.hutool.core.util.ReflectUtil;
|
|||||||
import cn.hutool.extra.spring.SpringUtil;
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.apache.ibatis.plugin.*;
|
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.constant.StringConstants;
|
||||||
import top.continew.starter.core.exception.BusinessException;
|
import top.continew.starter.core.exception.BusinessException;
|
||||||
import top.continew.starter.security.crypto.annotation.FieldEncrypt;
|
import top.continew.starter.security.crypto.annotation.FieldEncrypt;
|
||||||
@@ -46,39 +48,6 @@ public abstract class AbstractMyBatisInterceptor implements Interceptor {
|
|||||||
|
|
||||||
private static final Map<String, Map<String, FieldEncrypt>> ENCRYPT_PARAM_CACHE = new ConcurrentHashMap<>();
|
private static final Map<String, Map<String, FieldEncrypt>> ENCRYPT_PARAM_CACHE = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取加密参数
|
|
||||||
*
|
|
||||||
* @param mappedStatementId 映射语句 ID
|
|
||||||
* @return 加密参数
|
|
||||||
*/
|
|
||||||
public Map<String, FieldEncrypt> getEncryptParams(String mappedStatementId) {
|
|
||||||
return getEncryptParams(mappedStatementId, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取加密参数
|
|
||||||
*
|
|
||||||
* @param mappedStatementId 映射语句 ID
|
|
||||||
* @param parameterIndex 参数索引
|
|
||||||
* @return 加密参数
|
|
||||||
*/
|
|
||||||
public Map<String, FieldEncrypt> getEncryptParams(String mappedStatementId, Integer parameterIndex) {
|
|
||||||
return ENCRYPT_PARAM_CACHE
|
|
||||||
.computeIfAbsent(mappedStatementId, key -> getEncryptParamsNoCached(mappedStatementId, parameterIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取参数名称
|
|
||||||
*
|
|
||||||
* @param parameter 参数
|
|
||||||
* @return 参数名称
|
|
||||||
*/
|
|
||||||
public String getParameterName(Parameter parameter) {
|
|
||||||
Param param = parameter.getAnnotation(Param.class);
|
|
||||||
return null != param ? param.value() : parameter.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有字符串类型、需要加/解密的、有值字段
|
* 获取所有字符串类型、需要加/解密的、有值字段
|
||||||
*
|
*
|
||||||
@@ -114,13 +83,67 @@ public abstract class AbstractMyBatisInterceptor implements Interceptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取参数列表(无缓存)
|
* 获取加密参数
|
||||||
|
*
|
||||||
|
* @param mappedStatement 映射语句
|
||||||
|
* @return 加密参数
|
||||||
|
*/
|
||||||
|
public Map<String, FieldEncrypt> getEncryptParams(MappedStatement mappedStatement) {
|
||||||
|
return getEncryptParams(mappedStatement, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取加密参数
|
||||||
|
*
|
||||||
|
* @param mappedStatement 映射语句
|
||||||
|
* @param parameterCount 参数数量
|
||||||
|
* @return 加密参数
|
||||||
|
*/
|
||||||
|
public Map<String, FieldEncrypt> 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 mappedStatementId 映射语句 ID
|
||||||
* @param parameterIndex 参数数量
|
* @param parameterCount 参数数量
|
||||||
* @return 参数列表
|
* @return 加密参数列表
|
||||||
*/
|
*/
|
||||||
private Map<String, FieldEncrypt> getEncryptParamsNoCached(String mappedStatementId, Integer parameterIndex) {
|
private Map<String, FieldEncrypt> 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 {
|
try {
|
||||||
String className = CharSequenceUtil.subBefore(mappedStatementId, StringConstants.DOT, true);
|
String className = CharSequenceUtil.subBefore(mappedStatementId, StringConstants.DOT, true);
|
||||||
String wrapperMethodName = CharSequenceUtil.subAfter(mappedStatementId, StringConstants.DOT, true);
|
String wrapperMethodName = CharSequenceUtil.subAfter(mappedStatementId, StringConstants.DOT, true);
|
||||||
@@ -131,35 +154,42 @@ public abstract class AbstractMyBatisInterceptor implements Interceptor {
|
|||||||
.orElse(wrapperMethodName);
|
.orElse(wrapperMethodName);
|
||||||
// 获取真实方法
|
// 获取真实方法
|
||||||
Optional<Method> methodOptional = Arrays.stream(ReflectUtil.getMethods(Class.forName(className), m -> {
|
Optional<Method> methodOptional = Arrays.stream(ReflectUtil.getMethods(Class.forName(className), m -> {
|
||||||
if (Objects.nonNull(parameterIndex)) {
|
if (parameterCount != null) {
|
||||||
return Objects.equals(m.getName(), methodName) && m.getParameterCount() == parameterIndex;
|
return Objects.equals(m.getName(), methodName) && m.getParameterCount() == parameterCount;
|
||||||
}
|
}
|
||||||
return Objects.equals(m.getName(), methodName);
|
return Objects.equals(m.getName(), methodName);
|
||||||
})).findFirst();
|
})).findFirst();
|
||||||
if (methodOptional.isEmpty()) {
|
return methodOptional.orElse(null);
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
// 获取方法中的加密参数
|
|
||||||
Map<String, FieldEncrypt> map = MapUtil.newHashMap();
|
|
||||||
Parameter[] parameterArr = methodOptional.get().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;
|
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
throw new BusinessException(e.getMessage());
|
throw new BusinessException(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取加密参数列表
|
||||||
|
*
|
||||||
|
* @param method 方法
|
||||||
|
* @return 加密参数列表
|
||||||
|
*/
|
||||||
|
private Map<String, FieldEncrypt> getEncryptParams(Method method) {
|
||||||
|
// 获取方法中的加密参数
|
||||||
|
Map<String, FieldEncrypt> 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;
|
||||||
|
}
|
||||||
}
|
}
|
@@ -109,8 +109,10 @@ public class MyBatisEncryptInterceptor extends AbstractMyBatisInterceptor {
|
|||||||
* @throws Exception /
|
* @throws Exception /
|
||||||
*/
|
*/
|
||||||
private void encryptMap(HashMap<String, Object> parameterMap, MappedStatement mappedStatement) throws Exception {
|
private void encryptMap(HashMap<String, Object> parameterMap, MappedStatement mappedStatement) throws Exception {
|
||||||
Map<String, FieldEncrypt> encryptParamMap = super.getEncryptParams(mappedStatement.getId(), parameterMap
|
Map<String, FieldEncrypt> encryptParamMap = super.getEncryptParams(mappedStatement);
|
||||||
.isEmpty() ? null : parameterMap.size() / 2);
|
if (encryptParamMap.isEmpty() && !parameterMap.isEmpty()) {
|
||||||
|
encryptParamMap = super.getEncryptParams(mappedStatement, parameterMap.size() / 2);
|
||||||
|
}
|
||||||
for (Map.Entry<String, FieldEncrypt> encryptParamEntry : encryptParamMap.entrySet()) {
|
for (Map.Entry<String, FieldEncrypt> encryptParamEntry : encryptParamMap.entrySet()) {
|
||||||
String parameterName = encryptParamEntry.getKey();
|
String parameterName = encryptParamEntry.getKey();
|
||||||
if (parameterName.startsWith(Constants.ENTITY)) {
|
if (parameterName.startsWith(Constants.ENTITY)) {
|
||||||
|
Reference in New Issue
Block a user