build: db interceptor
This commit is contained in:
parent
25a2a3b601
commit
d74cae4ce8
|
@ -0,0 +1,33 @@
|
||||||
|
package io.metersphere.config;
|
||||||
|
|
||||||
|
import io.metersphere.sdk.interceptor.MybatisInterceptor;
|
||||||
|
import io.metersphere.sdk.util.CompressUtils;
|
||||||
|
import io.metersphere.sdk.util.MybatisInterceptorConfig;
|
||||||
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@MapperScan(basePackages = {"io.metersphere.*.mapper"}, sqlSessionFactoryRef = "sqlSessionFactory")
|
||||||
|
@EnableTransactionManagement
|
||||||
|
public class MybatisConfig {
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public MybatisInterceptor dbInterceptor() {
|
||||||
|
MybatisInterceptor interceptor = new MybatisInterceptor();
|
||||||
|
List<MybatisInterceptorConfig> configList = new ArrayList<>();
|
||||||
|
// configList.add(new MybatisInterceptorConfig(FileContent.class, "file", CompressUtils.class, "zip", "unZip"));
|
||||||
|
// configList.add(new MybatisInterceptorConfig(ApiTestReportDetail.class, "content", CompressUtils.class, "gzip", "unGzip"));
|
||||||
|
// configList.add(new MybatisInterceptorConfig(TestResource.class, "configuration"));
|
||||||
|
// configList.add(new MybatisInterceptorConfig(AuthSource.class, "configuration"));
|
||||||
|
// configList.add(new MybatisInterceptorConfig(LoadTestReportLog.class, "content", CompressUtils.class, "zipString", "unZipString"));
|
||||||
|
interceptor.setInterceptorConfigList(configList);
|
||||||
|
return interceptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,204 @@
|
||||||
|
package io.metersphere.sdk.interceptor;
|
||||||
|
|
||||||
|
import io.metersphere.sdk.util.BeanUtils;
|
||||||
|
import io.metersphere.sdk.util.MybatisInterceptorConfig;
|
||||||
|
import org.apache.commons.collections.MapUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.ibatis.cache.CacheKey;
|
||||||
|
import org.apache.ibatis.executor.Executor;
|
||||||
|
import org.apache.ibatis.mapping.BoundSql;
|
||||||
|
import org.apache.ibatis.mapping.MappedStatement;
|
||||||
|
import org.apache.ibatis.plugin.*;
|
||||||
|
import org.apache.ibatis.session.ResultHandler;
|
||||||
|
import org.apache.ibatis.session.RowBounds;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
@Intercepts({
|
||||||
|
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
|
||||||
|
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
|
||||||
|
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
|
||||||
|
})
|
||||||
|
public class MybatisInterceptor implements Interceptor {
|
||||||
|
|
||||||
|
private List<MybatisInterceptorConfig> interceptorConfigList;
|
||||||
|
|
||||||
|
private ConcurrentHashMap<String, Class> classMap = new ConcurrentHashMap<>();
|
||||||
|
private ConcurrentHashMap<String, Map<String, Map<String, MybatisInterceptorConfig>>> interceptorConfigMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object intercept(Invocation invocation) throws Throwable {
|
||||||
|
String methodName = invocation.getMethod().getName();
|
||||||
|
Object parameter = invocation.getArgs()[1];
|
||||||
|
if (parameter != null && methodName.equals("update")) {
|
||||||
|
invocation.getArgs()[1] = process(parameter);
|
||||||
|
}
|
||||||
|
Object returnValue = invocation.proceed();
|
||||||
|
Object result = returnValue;
|
||||||
|
if (returnValue instanceof ArrayList<?>) {
|
||||||
|
List<Object> list = new ArrayList<>();
|
||||||
|
boolean isDecrypted = false;
|
||||||
|
for (Object val : (ArrayList<?>) returnValue) {
|
||||||
|
Object a = undo(val);
|
||||||
|
if (a != val) {
|
||||||
|
isDecrypted = true;
|
||||||
|
list.add(a);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isDecrypted) {
|
||||||
|
result = list;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = undo(returnValue);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Map<String, MybatisInterceptorConfig>> getConfig(Object p) {
|
||||||
|
Map<String, Map<String, MybatisInterceptorConfig>> result = new HashMap<>();
|
||||||
|
if (p == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String pClassName = p.getClass().getName();
|
||||||
|
if (interceptorConfigMap.get(pClassName) != null) {
|
||||||
|
return interceptorConfigMap.get(pClassName);
|
||||||
|
}
|
||||||
|
Map<String, List<MybatisInterceptorConfig>> m = new HashMap<>();
|
||||||
|
for (MybatisInterceptorConfig interceptorConfig : interceptorConfigList) {
|
||||||
|
String className = interceptorConfig.getModelName();
|
||||||
|
String attrName = interceptorConfig.getAttrName();
|
||||||
|
if (StringUtils.isNotBlank(className)) {
|
||||||
|
Class c = classMap.get(className);
|
||||||
|
if (c == null) {
|
||||||
|
try {
|
||||||
|
c = Class.forName(className);
|
||||||
|
classMap.put(className, c);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c.isInstance(p)) {
|
||||||
|
if (result.get(attrName) == null) {
|
||||||
|
result.put(attrName, new HashMap<>());
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(interceptorConfig.getInterceptorMethod())) {
|
||||||
|
result.get(attrName).put(Methods.encrypt.name(), interceptorConfig);
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(interceptorConfig.getInterceptorMethod())) {
|
||||||
|
result.get(attrName).put(Methods.decrypt.name(), interceptorConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
interceptorConfigMap.put(pClassName, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object process(Object obj) throws Throwable {
|
||||||
|
if (obj instanceof Map) {
|
||||||
|
Map paramMap = (Map) obj;
|
||||||
|
for (Object key : paramMap.keySet()) {
|
||||||
|
if (paramMap.get(key) != null) {
|
||||||
|
paramMap.put(key, process(paramMap.get(key)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return paramMap;
|
||||||
|
}
|
||||||
|
Map<String, Map<String, MybatisInterceptorConfig>> localInterceptorConfigMap = getConfig(obj);
|
||||||
|
if (MapUtils.isEmpty(localInterceptorConfigMap)) {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
Object newObject = obj.getClass().newInstance();
|
||||||
|
BeanUtils.copyBean(newObject, obj);
|
||||||
|
for (String attrName : localInterceptorConfigMap.keySet()) {
|
||||||
|
if (MapUtils.isEmpty(localInterceptorConfigMap.get(attrName))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
MybatisInterceptorConfig interceptorConfig = localInterceptorConfigMap.get(attrName).get(Methods.encrypt.name());
|
||||||
|
if (interceptorConfig == null || StringUtils.isBlank(interceptorConfig.getInterceptorClass())
|
||||||
|
|| StringUtils.isBlank(interceptorConfig.getInterceptorMethod())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Object fieldValue = BeanUtils.getFieldValueByName(interceptorConfig.getAttrName(), newObject);
|
||||||
|
if (fieldValue != null) {
|
||||||
|
Class<?> processClazz = Class.forName(interceptorConfig.getInterceptorClass());
|
||||||
|
Method method = processClazz.getMethod(interceptorConfig.getInterceptorMethod(), Object.class);
|
||||||
|
Object processedValue = method.invoke(null, fieldValue);
|
||||||
|
if (processedValue instanceof byte[]) {
|
||||||
|
BeanUtils.setFieldValueByName(newObject, interceptorConfig.getAttrName(), processedValue, byte[].class);
|
||||||
|
} else {
|
||||||
|
BeanUtils.setFieldValueByName(newObject, interceptorConfig.getAttrName(), processedValue, fieldValue.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object undo(Object obj) throws Throwable {
|
||||||
|
Map<String, Map<String, MybatisInterceptorConfig>> localDecryptConfigMap = getConfig(obj);
|
||||||
|
Object result;
|
||||||
|
if (MapUtils.isEmpty(localDecryptConfigMap)) {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
result = obj.getClass().newInstance();
|
||||||
|
BeanUtils.copyBean(result, obj);
|
||||||
|
for (String attrName : localDecryptConfigMap.keySet()) {
|
||||||
|
if (MapUtils.isEmpty(localDecryptConfigMap.get(attrName))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
MybatisInterceptorConfig interceptorConfig = localDecryptConfigMap.get(attrName).get(Methods.decrypt.name());
|
||||||
|
if (interceptorConfig == null || StringUtils.isBlank(interceptorConfig.getUndoClass())
|
||||||
|
|| StringUtils.isBlank(interceptorConfig.getUndoMethod())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Object fieldValue = BeanUtils.getFieldValueByName(interceptorConfig.getAttrName(), result);
|
||||||
|
if (fieldValue != null) {
|
||||||
|
Class<?> processClazz = Class.forName(interceptorConfig.getUndoClass());
|
||||||
|
Object undoValue;
|
||||||
|
if (fieldValue instanceof List) {
|
||||||
|
Method method = processClazz.getMethod(interceptorConfig.getUndoMethod(), List.class, String.class);
|
||||||
|
//fieldValue获取的是list的引用,所以list类型的属性不需要再调用setFieldValueByName了
|
||||||
|
method.invoke(null, fieldValue, interceptorConfig.getAttrNameForList());
|
||||||
|
} else {
|
||||||
|
Method method = processClazz.getMethod(interceptorConfig.getUndoMethod(), Object.class);
|
||||||
|
undoValue = method.invoke(null, fieldValue);
|
||||||
|
if (undoValue instanceof byte[]) {
|
||||||
|
BeanUtils.setFieldValueByName(result, interceptorConfig.getAttrName(), undoValue, byte[].class);
|
||||||
|
} else {
|
||||||
|
BeanUtils.setFieldValueByName(result, interceptorConfig.getAttrName(), undoValue, fieldValue.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object plugin(Object target) {
|
||||||
|
return Plugin.wrap(target, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setProperties(Properties properties) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MybatisInterceptorConfig> getInterceptorConfigList() {
|
||||||
|
return interceptorConfigList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInterceptorConfigList(List<MybatisInterceptorConfig> interceptorConfigList) {
|
||||||
|
this.interceptorConfigList = interceptorConfigList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum Methods {
|
||||||
|
encrypt, decrypt
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package io.metersphere.sdk.util;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
public class BeanUtils {
|
||||||
|
|
||||||
|
public static <T> T copyBean(T target, Object source) {
|
||||||
|
try {
|
||||||
|
org.springframework.beans.BeanUtils.copyProperties(source, target);
|
||||||
|
return target;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Failed to copy object: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T copyBean(T target, Object source, String... ignoreProperties) {
|
||||||
|
try {
|
||||||
|
org.springframework.beans.BeanUtils.copyProperties(source, target, ignoreProperties);
|
||||||
|
return target;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Failed to copy object: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object getFieldValueByName(String fieldName, Object bean) {
|
||||||
|
try {
|
||||||
|
if (StringUtils.isBlank(fieldName)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String firstLetter = fieldName.substring(0, 1).toUpperCase();
|
||||||
|
String getter = "get" + firstLetter + fieldName.substring(1);
|
||||||
|
Method method = bean.getClass().getMethod(getter);
|
||||||
|
return method.invoke(bean);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setFieldValueByName(Object bean, String fieldName, Object value, Class<?> type) {
|
||||||
|
try {
|
||||||
|
if (StringUtils.isBlank(fieldName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String firstLetter = fieldName.substring(0, 1).toUpperCase();
|
||||||
|
String setter = "set" + firstLetter + fieldName.substring(1);
|
||||||
|
Method method = bean.getClass().getMethod(setter, type);
|
||||||
|
method.invoke(bean, value);
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Method getMethod(Object bean, String fieldName, Class<?> type) {
|
||||||
|
try {
|
||||||
|
if (StringUtils.isBlank(fieldName)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String firstLetter = fieldName.substring(0, 1).toUpperCase();
|
||||||
|
String setter = "set" + firstLetter + fieldName.substring(1);
|
||||||
|
return bean.getClass().getMethod(setter, type);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,167 @@
|
||||||
|
package io.metersphere.sdk.util;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import javax.crypto.*;
|
||||||
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密解密工具
|
||||||
|
*
|
||||||
|
* @author kun.mo
|
||||||
|
*/
|
||||||
|
public class CodingUtil {
|
||||||
|
|
||||||
|
private static final String UTF_8 = "UTF-8";
|
||||||
|
|
||||||
|
private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MD5加密
|
||||||
|
*
|
||||||
|
* @param src 要加密的串
|
||||||
|
* @return 加密后的字符串
|
||||||
|
*/
|
||||||
|
public static String md5(String src) {
|
||||||
|
return md5(src, UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MD5加密
|
||||||
|
*
|
||||||
|
* @param src 要加密的串
|
||||||
|
* @param charset 加密字符集
|
||||||
|
* @return 加密后的字符串
|
||||||
|
*/
|
||||||
|
public static String md5(String src, String charset) {
|
||||||
|
try {
|
||||||
|
byte[] strTemp = StringUtils.isEmpty(charset) ? src.getBytes() : src.getBytes(charset);
|
||||||
|
MessageDigest mdTemp = MessageDigest.getInstance("MD5");
|
||||||
|
mdTemp.update(strTemp);
|
||||||
|
|
||||||
|
byte[] md = mdTemp.digest();
|
||||||
|
int j = md.length;
|
||||||
|
char[] str = new char[j * 2];
|
||||||
|
int k = 0;
|
||||||
|
|
||||||
|
for (byte byte0 : md) {
|
||||||
|
str[k++] = HEX_DIGITS[byte0 >>> 4 & 0xf];
|
||||||
|
str[k++] = HEX_DIGITS[byte0 & 0xf];
|
||||||
|
}
|
||||||
|
|
||||||
|
return new String(str);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("MD5 encrypt error:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BASE64解密
|
||||||
|
*
|
||||||
|
* @param src 待解密的字符串
|
||||||
|
* @return 解密后的字符串
|
||||||
|
*/
|
||||||
|
public static String base64Decoding(String src) {
|
||||||
|
byte[] b;
|
||||||
|
String result = null;
|
||||||
|
if (src != null) {
|
||||||
|
try {
|
||||||
|
b = Base64.decodeBase64(src);
|
||||||
|
result = new String(b, UTF_8);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("BASE64 decoding error:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BASE64加密
|
||||||
|
*
|
||||||
|
* @param src 待加密的字符串
|
||||||
|
* @return 加密后的字符串
|
||||||
|
*/
|
||||||
|
public static String base64Encoding(String src) {
|
||||||
|
String result = null;
|
||||||
|
if (src != null) {
|
||||||
|
try {
|
||||||
|
result = Base64.encodeBase64String(src.getBytes(UTF_8));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("BASE64 encoding error:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES加密
|
||||||
|
*
|
||||||
|
* @param src 待加密字符串
|
||||||
|
* @param secretKey 密钥
|
||||||
|
* @param iv 向量
|
||||||
|
* @return 加密后字符串
|
||||||
|
*/
|
||||||
|
public static String aesEncrypt(String src, String secretKey, String iv) {
|
||||||
|
if (StringUtils.isBlank(secretKey)) {
|
||||||
|
throw new RuntimeException("secretKey is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
byte[] raw = secretKey.getBytes(UTF_8);
|
||||||
|
SecretKeySpec secretKeySpec = new SecretKeySpec(raw, "AES");
|
||||||
|
// "算法/模式/补码方式" ECB
|
||||||
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||||
|
IvParameterSpec iv1 = new IvParameterSpec(iv.getBytes());
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, iv1);
|
||||||
|
byte[] encrypted = cipher.doFinal(src.getBytes(UTF_8));
|
||||||
|
return Base64.encodeBase64String(encrypted);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("AES encrypt error:", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES 解密
|
||||||
|
*
|
||||||
|
* @param src 待解密字符串
|
||||||
|
* @param secretKey 密钥
|
||||||
|
* @param iv 向量
|
||||||
|
* @return 解密后字符串
|
||||||
|
*/
|
||||||
|
public static String aesDecrypt(String src, String secretKey, String iv) {
|
||||||
|
if (StringUtils.isBlank(secretKey)) {
|
||||||
|
throw new RuntimeException("secretKey is empty");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
byte[] raw = secretKey.getBytes(UTF_8);
|
||||||
|
SecretKeySpec secretKeySpec = new SecretKeySpec(raw, "AES");
|
||||||
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||||
|
IvParameterSpec iv1 = new IvParameterSpec(iv.getBytes());
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, iv1);
|
||||||
|
byte[] encrypted1 = Base64.decodeBase64(src);
|
||||||
|
byte[] original = cipher.doFinal(encrypted1);
|
||||||
|
return new String(original, UTF_8);
|
||||||
|
} catch (BadPaddingException | IllegalBlockSizeException e) {
|
||||||
|
// 解密的原字符串为非加密字符串,则直接返回原字符串
|
||||||
|
return src;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("decrypt error,please check parameters", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String secretKey() {
|
||||||
|
try {
|
||||||
|
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
|
||||||
|
keyGen.init(128);
|
||||||
|
SecretKey secretKey = keyGen.generateKey();
|
||||||
|
return Base64.encodeBase64String(secretKey.getEncoded());
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("generate secretKey error", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,237 @@
|
||||||
|
package io.metersphere.sdk.util;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.zip.*;
|
||||||
|
|
||||||
|
public class CompressUtils {
|
||||||
|
private final static String ZIP_PATH = "/opt/metersphere/data/tmp/";
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Zip压缩
|
||||||
|
*
|
||||||
|
* @param data 待压缩数据
|
||||||
|
* @return 压缩后数据
|
||||||
|
*/
|
||||||
|
public static Object zip(Object data) {
|
||||||
|
if (!(data instanceof byte[])) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] temp = (byte[]) data;
|
||||||
|
byte[] b = (byte[]) data;
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
ZipOutputStream zip = new ZipOutputStream(bos);
|
||||||
|
ZipEntry entry = new ZipEntry("zip");
|
||||||
|
entry.setSize(temp.length);
|
||||||
|
zip.putNextEntry(entry);
|
||||||
|
zip.write(temp);
|
||||||
|
zip.closeEntry();
|
||||||
|
zip.close();
|
||||||
|
b = bos.toByteArray();
|
||||||
|
bos.close();
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static File getFile(String fileName) throws IOException {
|
||||||
|
// 创建文件对象
|
||||||
|
File file;
|
||||||
|
if (ZIP_PATH != null && !ZIP_PATH.equals("")) {
|
||||||
|
file = new File(ZIP_PATH, fileName);
|
||||||
|
} else {
|
||||||
|
file = new File(fileName);
|
||||||
|
}
|
||||||
|
if (!file.exists()) {
|
||||||
|
file.createNewFile();
|
||||||
|
}
|
||||||
|
// 返回文件
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FileOutputStream getFileStream(File file) throws FileNotFoundException {
|
||||||
|
return new FileOutputStream(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void zipFile(File file, ZipOutputStream zipOutputStream) throws IOException {
|
||||||
|
if (file.exists()) {
|
||||||
|
if (file.isFile()) {
|
||||||
|
FileInputStream fis = new FileInputStream(file);
|
||||||
|
BufferedInputStream bis = new BufferedInputStream(fis);
|
||||||
|
ZipEntry entry = new ZipEntry(file.getName());
|
||||||
|
zipOutputStream.putNextEntry(entry);
|
||||||
|
|
||||||
|
final int MAX_BYTE = 10 * 1024 * 1024; // 最大流为10MB
|
||||||
|
long streamTotal = 0; // 接收流的容量
|
||||||
|
int streamNum = 0; // 需要分开的流数目
|
||||||
|
int leaveByte = 0; // 文件剩下的字符数
|
||||||
|
byte[] buffer; // byte数据接受文件的数据
|
||||||
|
|
||||||
|
streamTotal = bis.available(); // 获取流的最大字符数
|
||||||
|
streamNum = (int) Math.floor(streamTotal / MAX_BYTE);
|
||||||
|
leaveByte = (int) (streamTotal % MAX_BYTE);
|
||||||
|
|
||||||
|
if (streamNum > 0) {
|
||||||
|
for (int i = 0; i < streamNum; i++) {
|
||||||
|
buffer = new byte[MAX_BYTE];
|
||||||
|
bis.read(buffer, 0, MAX_BYTE);
|
||||||
|
zipOutputStream.write(buffer, 0, MAX_BYTE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入剩下的流数据
|
||||||
|
buffer = new byte[leaveByte];
|
||||||
|
bis.read(buffer, 0, leaveByte); // 读入流
|
||||||
|
zipOutputStream.write(buffer, 0, leaveByte); // 写入流
|
||||||
|
zipOutputStream.closeEntry(); // 关闭当前的zip entry
|
||||||
|
|
||||||
|
// 关闭输入流
|
||||||
|
bis.close();
|
||||||
|
fis.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将多个文件压缩
|
||||||
|
*
|
||||||
|
* @param fileList 待压缩的文件列表
|
||||||
|
* @param zipFileName 压缩文件名
|
||||||
|
* @return 返回压缩好的文件
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static File zipFiles(String zipFileName, List<File> fileList) throws IOException {
|
||||||
|
File zipFile = getFile(zipFileName);
|
||||||
|
// 文件输出流
|
||||||
|
FileOutputStream outputStream = getFileStream(zipFile);
|
||||||
|
// 压缩流
|
||||||
|
ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
|
||||||
|
|
||||||
|
int size = fileList.size();
|
||||||
|
// 压缩列表中的文件
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
File file = fileList.get(i);
|
||||||
|
zipFile(file, zipOutputStream);
|
||||||
|
}
|
||||||
|
// 关闭压缩流、文件流
|
||||||
|
zipOutputStream.close();
|
||||||
|
outputStream.close();
|
||||||
|
return zipFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Zip解压
|
||||||
|
*
|
||||||
|
* @param data 待解压数据
|
||||||
|
* @return 解压后数据
|
||||||
|
*/
|
||||||
|
public static Object unZip(Object data) {
|
||||||
|
if (!(data instanceof byte[])) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
byte[] temp = (byte[]) data;
|
||||||
|
byte[] b = (byte[]) data;
|
||||||
|
try {
|
||||||
|
ByteArrayInputStream bis = new ByteArrayInputStream(temp);
|
||||||
|
ZipInputStream zip = new ZipInputStream(bis);
|
||||||
|
while (zip.getNextEntry() != null) {
|
||||||
|
byte[] buf = new byte[1024];
|
||||||
|
int num;
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
while ((num = zip.read(buf, 0, buf.length)) != -1) {
|
||||||
|
baos.write(buf, 0, num);
|
||||||
|
}
|
||||||
|
b = baos.toByteArray();
|
||||||
|
baos.flush();
|
||||||
|
baos.close();
|
||||||
|
}
|
||||||
|
zip.close();
|
||||||
|
bis.close();
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GZip压缩
|
||||||
|
*
|
||||||
|
* @param data 待压缩数据
|
||||||
|
* @return 压缩后数
|
||||||
|
*/
|
||||||
|
public static Object gzip(Object data) {
|
||||||
|
if (!(data instanceof byte[])) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
byte[] bytes = (byte[]) data;
|
||||||
|
try (ByteArrayOutputStream obj = new ByteArrayOutputStream(); GZIPOutputStream gzip = new GZIPOutputStream(obj)) {
|
||||||
|
gzip.write(bytes);
|
||||||
|
gzip.flush();
|
||||||
|
gzip.finish();
|
||||||
|
return obj.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GZip解压
|
||||||
|
*
|
||||||
|
* @param data 待解压数据
|
||||||
|
* @return 解压后数据
|
||||||
|
*/
|
||||||
|
public static Object unGzip(Object data) {
|
||||||
|
if (!(data instanceof byte[])) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
byte[] bytes = (byte[]) data;
|
||||||
|
if (bytes.length == 0) {
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
try (GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(bytes)); ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
int len;
|
||||||
|
while ((len = gis.read(buffer)) > 0) {
|
||||||
|
baos.write(buffer, 0, len);
|
||||||
|
}
|
||||||
|
baos.flush();
|
||||||
|
return baos.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object zipString(Object data) {
|
||||||
|
if (!(data instanceof String)) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
||||||
|
try (DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(out)) {
|
||||||
|
deflaterOutputStream.write(((String) data).getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
return Base64.encodeBase64String(out.toByteArray());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object unZipString(Object data) {
|
||||||
|
if (!(data instanceof String)) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
|
||||||
|
try (OutputStream outputStream = new InflaterOutputStream(os)) {
|
||||||
|
outputStream.write(Base64.decodeBase64((String) data));
|
||||||
|
}
|
||||||
|
return os.toString(StandardCharsets.UTF_8);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package io.metersphere.sdk.util;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class EncryptUtils extends CodingUtil {
|
||||||
|
|
||||||
|
private static final String secretKey = "www.fit2cloud.co";
|
||||||
|
private static final String iv = "1234567890123456";
|
||||||
|
|
||||||
|
|
||||||
|
public static Object aesEncrypt(Object o) {
|
||||||
|
if (o == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return aesEncrypt(o.toString(), secretKey, iv);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object aesDecrypt(Object o) {
|
||||||
|
if (o == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return aesDecrypt(o.toString(), secretKey, iv);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Object aesDecrypt(List<T> o, String attrName) {
|
||||||
|
if (o == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return o.stream()
|
||||||
|
.filter(element -> BeanUtils.getFieldValueByName(attrName, element) != null)
|
||||||
|
.peek(element -> BeanUtils.setFieldValueByName(element, attrName, aesDecrypt(BeanUtils.getFieldValueByName(attrName, element).toString(), secretKey, iv), String.class))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object md5Encrypt(Object o) {
|
||||||
|
if (o == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return md5(o.toString());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package io.metersphere.sdk.util;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class MybatisInterceptorConfig {
|
||||||
|
private String modelName;
|
||||||
|
private String attrName;
|
||||||
|
private String attrNameForList;
|
||||||
|
private String interceptorClass;
|
||||||
|
private String interceptorMethod;
|
||||||
|
private String undoClass;
|
||||||
|
private String undoMethod;
|
||||||
|
|
||||||
|
public MybatisInterceptorConfig() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用时需谨慎!!!!!
|
||||||
|
* 主要配置多个的时候,参数少一点
|
||||||
|
*
|
||||||
|
* @param modelClass
|
||||||
|
* @param attrName
|
||||||
|
*/
|
||||||
|
public MybatisInterceptorConfig(Class<?> modelClass, String attrName) {
|
||||||
|
this.modelName = modelClass.getName();
|
||||||
|
this.attrName = attrName;
|
||||||
|
this.interceptorClass = EncryptUtils.class.getName();
|
||||||
|
this.interceptorMethod = "aesEncrypt";
|
||||||
|
this.undoClass = EncryptUtils.class.getName();
|
||||||
|
this.undoMethod = "aesDecrypt";
|
||||||
|
}
|
||||||
|
|
||||||
|
public MybatisInterceptorConfig(Class<?> modelClass, String attrName, Class<?> interceptorClass, String interceptorMethod, String undoMethod) {
|
||||||
|
this.modelName = modelClass.getName();
|
||||||
|
this.attrName = attrName;
|
||||||
|
this.interceptorClass = interceptorClass.getName();
|
||||||
|
this.interceptorMethod = interceptorMethod;
|
||||||
|
this.undoClass = interceptorClass.getName();
|
||||||
|
this.undoMethod = undoMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue