feat: aos-mybatis-plus 增加数据入库加解密
This commit is contained in:
@@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
+11
@@ -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 {
|
||||
|
||||
}
|
||||
+12
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user