feat: aos-mybatis-plus 增加数据入库加解密

This commit is contained in:
王永亮
2022-11-16 22:24:31 +08:00
parent f25478c4a5
commit b8ff6ebdc2
10 changed files with 307 additions and 45 deletions
@@ -0,0 +1,52 @@
package com.aos.mybatis.plus;
import com.oak.mybatisplus.annotation.DecryptTransaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.util.Objects;
/**
* com.oak.mybatisplus.interceptor -> 解密字段
*/
@Component
public class DecryptImpl implements DecryptUtil {
@Autowired
private AESUtil aesUtil;
/**
* 解密
*
* @param result resultType的实例
* @param <T>
* @return
* @throws IllegalAccessException
*/
@Override
public <T> T decrypt(T result) throws IllegalAccessException {
//取出resultType的类
Class<?> resultClass = result.getClass();
Field[] declaredFields = resultClass.getDeclaredFields();
for (Field field : declaredFields) {
//取出所有被DecryptTransaction注解的字段
DecryptTransaction decryptTransaction = field.getAnnotation(DecryptTransaction.class);
if (!Objects.isNull(decryptTransaction)) {
field.setAccessible(true);
Object object = field.get(result);
//String的解密
if (object instanceof String) {
String value = (String) object;
//对注解的字段进行逐一解密
try {
field.set(result, aesUtil.decrypt(value));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return result;
}
}
@@ -0,0 +1,33 @@
package com.aos.mybatis.plus;
import org.springframework.stereotype.Component;
@Component
public class EncryptImpl implements EncryptUtil{
@Autowired
private AESUtil aesUtil;
@Override
public <T> T encrypt(Field[] declaredFields, T paramsObject) throws IllegalAccessException {
for (Field field : declaredFields) {
//取出所有被EncryptTransaction注解的字段
EncryptTransaction encryptTransaction = field.getAnnotation(EncryptTransaction.class);
if (!Objects.isNull(encryptTransaction)) {
field.setAccessible(true);
Object object = field.get(paramsObject);
//暂时只实现String类型的加密
if (object instanceof String) {
String value = (String) object;
//加密
try {
if(StrUtil.isNotBlank(value)){
field.set(paramsObject, aesUtil.encrypt(value));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return paramsObject;
}
}
@@ -0,0 +1,64 @@
package com.aos.mybatis.plus;
import com.oak.mybatisplus.annotation.SensitiveData;
import com.oak.mybatisplus.interceptor.handler.EncryptUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.plugin.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.util.Objects;
import java.util.Properties;
/**
* com.oak.mybatisplus.interceptor -> sql查询参数加密
*/
@Slf4j
@Component
@Intercepts({
@Signature(type = ParameterHandler.class, method = "setParameters", args = PreparedStatement.class),
})
public class ParameterInterceptor implements Interceptor {
@Autowired
private EncryptUtil encryptUtil;
@Override
public Object intercept(Invocation invocation) throws Throwable {
//@Signature 指定了 type= parameterHandler 后,这里的 invocation.getTarget() 便是parameterHandler
//若指定ResultSetHandler ,这里则能强转为ResultSetHandler
ParameterHandler parameterHandler = (ParameterHandler) invocation.getTarget();
// 获取参数对像,即 mapper 中 paramsType 的实例
Field parameterField = parameterHandler.getClass().getDeclaredField("parameterObject");
parameterField.setAccessible(true);
//取出实例
Object parameterObject = parameterField.get(parameterHandler);
if (parameterObject != null) {
Class<?> parameterObjectClass = parameterObject.getClass();
//校验该实例的类是否被@SensitiveData所注解
SensitiveData sensitiveData = AnnotationUtils.findAnnotation(parameterObjectClass, SensitiveData.class);
if (Objects.nonNull(sensitiveData)) {
//取出当前当前类所有字段,传入加密方法
Field[] declaredFields = parameterObjectClass.getDeclaredFields();
encryptUtil.encrypt(declaredFields, parameterObject);
}
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
@@ -0,0 +1,74 @@
package com.aos.mybatis.plus;
import com.oak.mybatisplus.annotation.SensitiveData;
import com.oak.mybatisplus.interceptor.handler.DecryptUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.CollectionUtils;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Properties;
/**
* com.oak.mybatisplus.interceptor -> sql返回结果解密
* @Date: 2022/10/24
*/
@Slf4j
@Component
@Intercepts({
@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
public class ResultSetInterceptor implements Interceptor {
@Autowired
private DecryptUtil decryptUtil;
@Override
public Object intercept(Invocation invocation) throws Throwable {
//取出查询的结果
Object resultObject = invocation.proceed();
if (Objects.isNull(resultObject)) {
return null;
}
//基于selectList
if (resultObject instanceof ArrayList) {
ArrayList resultList = (ArrayList) resultObject;
if (!CollectionUtils.isEmpty(resultList) && needToDecrypt(resultList.get(0))) {
for (Object result : resultList) {
//逐一解密
decryptUtil.decrypt(result);
}
}
//基于selectOne
} else {
if (needToDecrypt(resultObject)) {
decryptUtil.decrypt(resultObject);
}
}
return resultObject;
}
private boolean needToDecrypt(Object object) {
Class<?> objectClass = object.getClass();
SensitiveData sensitiveData = AnnotationUtils.findAnnotation(objectClass, SensitiveData.class);
return Objects.nonNull(sensitiveData);
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
@@ -0,0 +1,11 @@
package com.aos.mybatis.plus.annotation;
import java.lang.annotation.*;
@Documented
@Inherited
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DecryptTransaction {
}
@@ -0,0 +1,12 @@
package com.aos.mybatis.plus.annotation;
import java.lang.annotation.*;
/**
* 加密
*/
@Inherited
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptTransaction {
}
@@ -0,0 +1,12 @@
package com.aos.mybatis.plus.annotation;
import java.lang.annotation.*;
/**
* 脱敏注解
*/
@Inherited
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface SensitiveData {
}
@@ -4,7 +4,6 @@ import com.aos.robot.model.MegTypeEnum;
import com.aos.robot.model.wx.WxRobotParam;
import com.aos.robot.service.Robot;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@@ -29,56 +28,12 @@ public class RobotAlarm {
Map<String, Robot> robotMap;
public void alarm(String robootName, String message, Throwable error) {
String stackTrace = ExceptionUtils.getStackTrace(error);
message = message + "\n" + "错误信息:" + error.getMessage();
message = message + "\n" + stackTrace;
this.makeTextMessage(robootName, message.substring(0, 2000));
}
public void alarm(String robootName, String message, Object... value) {
String format = message;
if (value.length != 0) {
format = MessageFormat.format(message, value);
}
this.makeTextMessage(robootName, format);
}
public void markdown(String robotName, String message, Object... value) {
String format = MessageFormat.format(message, value);
this.makeMarkdownMessage(robotName, format);
}
private void makeMarkdownMessage(String robotName, String message) {
WxRobotParam robotParam = new WxRobotParam();
robotParam.setMsgtype(MegTypeEnum.MARKDOWN);
WxRobotParam.Markdown markdown = new WxRobotParam.Markdown();
message = "## 当前时间 " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "\n" + message;
markdown.setContent(message);
robotParam.setMarkdown(markdown);
this.send(robotName, robotParam);
}
private void makeTextMessage(String robotName, String message) {
message = "当前环境:" + env + "\n" + "当前时间:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "\n" + message;
WxRobotParam robotParam = new WxRobotParam();
WxRobotParam.Text text = new WxRobotParam.Text();
text.setContent(message);
robotParam.setText(text);
this.send(robotName, robotParam);
}
/**
* 发送文本格式消息
*
* @param robotName
* @param robotParam
* @return void
* @Date 2022/8/5
* @Author wangyl
*/
private void send(String robotName, WxRobotParam robotParam) {
robot.sendMessage(robotName, robotParam);
}
@@ -3,6 +3,7 @@ package com.aos.robot;
import com.aos.robot.conf.RobotInfo;
import com.aos.robot.model.MegTypeEnum;
import com.aos.robot.model.base.RobotPatam;
import com.aos.robot.model.wx.WxRobotParam;
import com.aos.robot.model.wx.WxRobotRes;
import com.aos.robot.service.AbstractRobot;
import lombok.extern.slf4j.Slf4j;
@@ -12,6 +13,8 @@ import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Slf4j
@Component
@@ -59,6 +62,7 @@ public class WxRobot extends AbstractRobot {
@Override
public void info(String robotName, MegTypeEnum messageTypeEnum, String message, Object... value) {
this.sendMessage();
}
/**
@@ -92,4 +96,24 @@ public class WxRobot extends AbstractRobot {
public void error(String robotName, MegTypeEnum messageTypeEnum, String message, Throwable error) {
}
private void makeMarkdownMessage(String robotName, String message) {
WxRobotParam robotParam = new WxRobotParam();
robotParam.setMsgtype(MegTypeEnum.MARKDOWN);
WxRobotParam.Markdown markdown = new WxRobotParam.Markdown();
message = "## 当前时间 " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "\n" + message;
markdown.setContent(message);
robotParam.setMarkdown(markdown);
this.send(robotName, robotParam);
}
private void makeTextMessage(String robotName, String message) {
message = "当前环境:" + env + "\n" + "当前时间:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "\n" + message;
WxRobotParam robotParam = new WxRobotParam();
WxRobotParam.Text text = new WxRobotParam.Text();
text.setContent(message);
robotParam.setText(text);
this.send(robotName, robotParam);
}
}
@@ -2,11 +2,16 @@ package com.aos.robot.service;
import com.aos.robot.conf.RobotConfig;
import com.aos.robot.conf.RobotInfo;
import com.aos.robot.model.MegTypeEnum;
import com.aos.robot.model.base.RobotPatam;
import com.aos.robot.model.wx.WxRobotParam;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public abstract class AbstractRobot implements Robot {
@Autowired
@@ -54,4 +59,24 @@ public abstract class AbstractRobot implements Robot {
*/
abstract protected void sendMessage(String robotName, RobotPatam robotParam);
private void makeMarkdownMessage(String robotName, String message) {
WxRobotParam robotParam = new WxRobotParam();
robotParam.setMsgtype(MegTypeEnum.MARKDOWN);
WxRobotParam.Markdown markdown = new WxRobotParam.Markdown();
message = "## 当前时间 " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "\n" + message;
markdown.setContent(message);
robotParam.setMarkdown(markdown);
this.send(robotName, robotParam);
}
private void makeTextMessage(String robotName, String message) {
message = "当前环境:" + env + "\n" + "当前时间:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "\n" + message;
WxRobotParam robotParam = new WxRobotParam();
WxRobotParam.Text text = new WxRobotParam.Text();
text.setContent(message);
robotParam.setText(text);
this.send(robotName, robotParam);
}
}