山海Guard
# 组件能力
- 支持文件上传安全检测 (支持全局校验、单个方法校验、自定义校验、ZIP扫描校验等多种策略)
- 支持基于Mybatis-Plus在进行数据字段级加密与脱敏(支持自行扩展实现相关算法,如对接密码机或加密服务)
- 支持SQL注入&XSS注入安全检测
- 支持密码复杂度检验 (支持数字、大小写字母、键盘排序、长度、相同字符、连续字符等多种策略)
- 支持SpringBoot POST请求报文加密、响应报文加密
- 支持SpringBoot 响应报文进行字段级数据脱敏(支持自行实现脱敏算法)
- 支持对SpringBoot配置文件任意参数进行参数加密(支持自行扩展加密算法)
- 支持对全量参数进行敏感词检查与过滤
# 1.引入依赖
<dependency>
<groupId>com.wangshanhai.guard</groupId>
<artifactId>shanhai-guard-spring-boot-starter</artifactId>
<version>${shanhaiguard.last.version}</version>
</dependency>
# 2.启用ShanHaiGuard安全防护组件
@Configuration
@EnableShanHaiGuard
public class ShanHaiGuardConfig {
}
# 3.组件说明
# 3.1 文件上传检测
配置参数如下
shanhai:
fileguard:
enable: true #启用组件
pathPatterns: #检测范围
- '/**'
suffix: jpg,gif,png,ico,bmp,jpeg #文件上传白名单
logTarce: true #启用跟踪日志
此处的配置为全局性配置,对于单个方法的校验,可以使用@FileGuard添加校验,参考下面样例的使用方式:
1)跳过检验
@FileGuard(skip = true)
2)实现自定义规则检验
@FileGuard(checkByRule = true)
注:如果启用该参数,需要实现FileGuardRuleDefService,否则将无法上传文件。
public class FileGuardRuleDefServiceImpl implements FileGuardRuleDefService {
/**
* 表单key及对应的文件
* @param files 文件清单
* @return
*/
@Override
public boolean isSafe(Map<String, MultipartFile> files) {
return true;
}
}
3)通过文件后缀校验(GuardType.SUFFIX)
/**
* 文件上传测试样例
* @param request
* @return
*/
@RequestMapping(value = "/file/suffix/upload")
@FileGuard(message = "只能上传图片文件",type = FileGuard.GuardType.SUFFIX,supportedSuffixes = {"png", "jpg", "jpeg"})
@ResponseBody
public String suffix(HttpServletRequest request, MultipartFile file){
Logger.info("[file-upload-api]-name:{},contentType:{},size:{}",file.getName(),file.getContentType(),file.getSize());
return "success";
}
4)通过二进制文件头检验(GuardType.BYTES)
/**
* 文件上传测试样例
* @param request
* @return
*/
@RequestMapping(value = "/file/bytes/upload")
@FileGuard(message = "只能上传图片文件",type = FileGuard.GuardType.BYTES,supportedFileTypes = {FileType.JPEG,FileType.PNG})
@ResponseBody
public String bytes(HttpServletRequest request, MultipartFile file){
Logger.info("[file-upload-api]-name:{},contentType:{},size:{}",file.getName(),file.getContentType(),file.getSize());
return "success";
}
注:单个方法的白名单必须为全局性白名单的子集
5)支持ZIP压缩包自动扫描检测
shanhai:
fileguard:
zipScan: true #启用组件
zipSafeSuffixs: jpg,gif,png,ico,bmp,jpeg #ZIP压缩包内文件上传白名单
6)排除某些特定URI校验
shanhai:
fileguard:
excludePathPatterns:
- '/**'
# 3.2 密码复杂度检测
配置参数如下
shanhai:
passwdguard:
enable: true #启用组件
minLength: 4 #最小长度
maxLength: 10 #最大长度
characterExist: true #包含大小写字母
numberExist: true #包含数字
symbolExist: true #包含符号
keyboardNotExist: true #不包含键盘排序
allSameNotExist: true #不包含相同字符(数字或字母,如111或aaa)
allSameNum: 3 #相同字符最大个数
seqSameNotExist: true #不包含连续字符(数字或字母,如123或abc)
seqSameNum: 3 #连续字符最大个数
mode: 1 #检测模式 1:配置模式 2:权重打分模式
min-weight: 1 #权重打分模式下最小打分值(符合一条规则则获的1分)
在业务模块可以直接使用密码复杂度检测服务PasswdService,示例如下:
//注入服务
@Autowired
private PasswdService passwdService;
//调用服务方法
passwdService.checkPasswd(passwd)
# 3.3 SQL&XSS注入检测
配置参数如下
shanhai:
webguard:
enable: true #启用组件
path-patterns: #检测范围
- '/*'
# 3.4 Mysql数据安全检测
配置参数如下
shanhai:
mysqlguard:
enable: true #启用组件
where-exist: false #包含where语句
limit-exist: false #包含limit语句
query-limit: 20000 #limit条数
# 3.5 @RequestBody 通用解码组件
# 3.5.1 全量请求解码
配置参数如下
shanhai:
decodebody:
enable: true #启用组件
注:此组件只是做了通用性封装,对于解码逻辑需要自行实现接口DecodeBodyService的decodeRequestBody方法,在进行数据解码时,会自动调用该接口的实现方法进行自定义参数解码操作。
接口定义如下:
public interface DecodeBodyService {
/**
* 解析加密参数
* @param body 原始报文数据
* @return
*/
public String decodeRequestBody(String body);
}
如果需要某个请求不进行解码操作,可以使用注解@DecodeBodyIgnore跳过对目标请求的解码操作。
# 3.5.2 指定请求解码
配置参数如下
shanhai:
decodebody:
enable: true #启用组件
mode: 2 #指定请求解码模式,默认为全量解码 mode:1
使用示例如下
@DecodeBody(ruleId = "demio")
@ResponseBody
public String decodeOne(@RequestBody String body){
return body;
}
注:此组件只是做了通用性封装,对于解码逻辑需要自行实现接口DecodeBodyService的decodeRequestBody方法,在进行数据解码时,会自动调用该接口的实现方法进行自定义参数解码操作。
接口定义如下:
public interface DecodeBodyService {
default String decodeRequestBody(String ruleId,String body)
}
用户根据ruleId进行个性化解码组件开发。
# 3.5.3 基于hutool的国密算法示例
//1、原始请求报文
String reqBody="张三@akandak11213";
//2、生成SM2公私钥
SM2 sm2 = SmUtil.sm2();
byte[] d = sm2.getD();
byte[] q = sm2.getQ(false);
String privateKey = HexUtil.encodeHexStr(d);
String publicKey = HexUtil.encodeHexStr(q);
System.out.println("SM2公钥:"+publicKey);
System.out.println("SM2私钥:"+privateKey);
//3、加密参数
String source= DateUtil.format(new Date(),"yyyyMMddHHmmssSSS").substring(0,16);
System.out.println("SM4加密key:"+source);
String sm4Iv="!koVE&dc#16K9@YW";
//4、执行SM2加密
String encryptStr= sm2.encryptHex(source,KeyType.PublicKey);
System.out.println("SM2加密结果:"+encryptStr);
System.out.println("SM2解密结果:"+sm2.decryptStr(encryptStr,KeyType.PrivateKey));
//5、执行SM4加密
SM4 sm4 = new SM4(Mode.CBC, Padding.PKCS5Padding,source.getBytes(),sm4Iv.getBytes());
JSONObject jsonObject=new JSONObject();
jsonObject.put("key",encryptStr);
jsonObject.put("content",sm4.encryptHex(reqBody));
//6、执行SM2解密
String sourceKey ="";
String sm2key=jsonObject.getString("key");
if(sm2key.startsWith("04")){
sourceKey = sm2.decryptStr(sm2key, KeyType.PrivateKey);
}else{
sourceKey = StrUtil.format("04{}",jsonObject.getString("key"));
}
//7、执行SM4解密
SM4 smDmic = new SM4(Mode.CBC, Padding.PKCS5Padding,sourceKey.getBytes(),sm4Iv.getBytes());
String content=smDmic.decryptStr(jsonObject.getString("content"));
System.out.println("解密报文:"+content);
国密算法vue版本:
https://github.com/JuneAndGreen/sm-crypto
# 3.6 SpringBoot配置文件参数加密
# 3.6.1 使用内置算法处理加密参数
内置解密算法(PBE)配置样例-(老版本实现,不再推荐使用)
shanhai:
envdecode:
market:
algorithm: PBE #算法名称
pebPasswd: '20220111' #密钥
pebSalt: 'XCWT61iHdbg=' #盐值
内置解密算法(PBE安全模式)配置样例
shanhai:
envdecode:
market:
algorithm: PBESafe #算法名称
pebPasswd: '20220111' #密钥
pebSalt: 'XCWT61iHdbg=' #盐值
cycleNum: 100000 #循环次数(必须大于10000)
内置解密算法(AES)配置样例
shanhai:
envdecode:
market:
algorithm: AES #算法名称
key: 'woniucsdnvip8888' #密钥 (16字节)
iv: 'bbCGNLlryzHaCL3P' #向量 (16字节)
mode: 1 #模式 1:CBC 2:CFB
SpringBoot配置参数加密说明:
1)所有加密参数的Value值以**envdecode:😗*打头,举例如下:
app:
version: 'envdecode::iezthxHWDp/fhXYXZSjhVw=='
2)加密结果生成样例
PBE加密算法
public static void main(String[] args) throws Exception {
//生成盐值
String salt= PBEUtils.initSalt();
//自定义密钥
String passwd="20220111";
//待加密参数值
String val="zhangsanxxx1";
String encryptStr=PBEUtils.encrypt(val,passwd,salt);
//加密结果
System.out.println(salt+":"+encryptStr);
//解密结果
System.out.println(PBEUtils.decrypt(encryptStr,passwd,salt));
}
PBE安全模式加密算法
public static void main(String[] args) throws Exception {
//生成盐值
String salt= PBEUtils.initSalt();
//自定义密钥
String passwd="20220111";
//待加密参数值
String val="zhangsanxxx1";
String encryptStr=PBEUtils.encryptSafe(val,passwd,salt,100000);
//加密结果
System.out.println(salt+":"+encryptStr);
//解密结果
System.out.println(PBEUtils.decryptSafe(encryptStr,passwd,salt,100000));
}
AES加密算法
public static void main(String[] args) {
String text = "嗨,您好!";
String key = "woniucsdnvip8888";
String iv = getIV();
String encryptTextCBC = encrypt(text, key, iv, AES_CBC);
System.out.println("CBC 加密IV:" + iv);
System.out.println("CBC 加密后内容:" + encryptTextCBC);
System.out.println("CBC 解密后内容:" + decrypt(encryptTextCBC, key, iv, AES_CBC));
System.out.println();
String encryptTextCFB = encrypt(text, key, iv, AES_CFB);
System.out.println("CFB 加密IV:" + iv);
System.out.println("CFB 加密后内容:" + encryptTextCFB);
System.out.println("CFB 解密后内容:" + decrypt(encryptTextCFB, key, iv, AES_CFB));
}
# 3.6.2 自定义处理加密参数
首先需要实现一个自己的参数解密类,要求该类必须继承于PropertyDecode,并实现其定义的解密方法getProperty,PropertyDecoded定义如下:
public abstract class PropertyDecode {
/**
* 自定义解析算法
* @param envProperties 通用配置参数
* @param configProperties 待解密属性key:value
* @return
*/
@Nullable
public abstract Properties getProperty(Properties envProperties,Properties configProperties);
}
注:SpringBoot配置文件中shanhai.envdecode打头的参数都会传递到envProperties中,可以自己获取自己配置的自定义参数。
在SpringBoot的配置文件中指定自己新增的自定义解密类,如下所示:
shanhai:
envdecode:
# 自定义解密类的优先级最高
className: 'com.xxx.RSAPropertyDecode'
注 :如果既存在自定义解密类,又存在PBE解密配置的,自定义解密类优先级最高。
# 3.7 基于Mybatis-Plus进行字段级加解密与数据脱敏
数据处理 | 生效模式 | 备注 |
---|---|---|
数据加密 | 新增|修改|查询 | 不支持 QueryWrapper进行查询 |
数据解密 | 查询 | |
数据脱敏 | 新增|修改|查询 | 当执行新增|修改操作时,脱敏与加密不建议同时使用 |
数据生效范围
范围定义 | 作用域 | 备注 |
---|---|---|
DataExecModel.INSERT | 数据新增操作 | |
DataExecModel.UPDATE | 数据更新操作 | |
DataExecModel.SELECT | 数据查询操作 | |
DataExecModel.INSERTANDUPDATE | 数据新增或更新操作 | |
DataExecModel.ALL | 数据新增|修改|查询操作 |
# 3.7.1 使用内置算法进行数据字段级加解密操作
配置参数如下:
shanhai:
dataguard:
enable: true #启用组件
trace-log: true #启用跟踪日志
slow-filter: true #启用慢监控
slow-time: 1000 #慢处理监控最小阈值(单位:ms)
encryptRulesExt: #加密算法参数配置(对称加密&非对称加密均需配置)
- {ruleId: 'AES', ruleParams: {key: wjy59188wjy59188}} #内置AES加密算法示例(key的长度为16位)
- {ruleId: 'SM4', ruleParams: {key: wjy59188wjy59188}} #内置SM4加密算法示例(key的长度为16位)
- {ruleId: 'HMACSHA256', ruleParams: {key: wjy59188wjy59188}} #内置HMACSHA256加密算法示例
- {ruleId: 'RSA', ruleParams: {publicKey: wjy59188wjy59188,privateKey: wjy59188wjy59188}} #内置RSA加密算法示例
- {ruleId: 'SM2', ruleParams: {publicKey: wjy59188wjy59188,privateKey: wjy59188wjy59188}} #内置SM2加密算法示例
注:此处的ruleId的值是示例,实际使用时需要修改为FieldDataGuard中定义的ruleId对应的值,ruleId必须自行确保全局唯一,否则数据解析会有问题。ruleParams中的参数,使用内置算法时,参数名必须为示例配置中的参数名才可以,相关key的值可以自己自定义。
如果需要使用国密算法,需要引入额外的依赖才可以
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>${bcprov.version}</version>
</dependency>
在Domain中添加类扫描注解@ShanHaiDataGuard,在需要操作的字段添加 @FieldDataGuard注解:
加密示例如下:
@ShanHaiDataGuard
public class DictData implements Serializable {
private static final long serialVersionUID = 1L;
@FieldDataGuard(ruleId = "dictLabel",encrypt = true,encryptMethod = DataEncryptDef.SHA256)
private String dictLabel;
}
解密示例如下:
@ShanHaiDataGuard
public class DictData implements Serializable {
private static final long serialVersionUID = 1L;
@FieldDataGuard(ruleId = "dictLabel",decrypt = true,decryptMethod = DataEncryptDef.AES,decryptExecModel = DataExecModel.SELECT)
private String dictLabel;
}
@FieldDataGuard 各字段定义
字段定义 | 字段类型 | 字段说明 |
---|---|---|
ruleId | String | 规则ID,用于自行根据规则进行相关扩展 |
encrypt | boolean | 是否启用数据加密 |
encryptMethod | String | 加密算法 默认算法集参考DataEncryptDef |
encryptExecModel | String | 执行加密算法的时机 参考DataExecModel |
decrypt | boolean | 是否启用数据查询解密 |
decryptMethod | String | 解密算法 默认算法集参考DataEncryptDef |
hyposensit | boolean | 是否启用数据脱敏 |
hyposensitMethod | String | 数据脱敏算法 默认算法集参考DataHyposensitDef |
hyposensitExecModel | String | 执行脱敏算法的时机 参考DataExecModel |
ShanHaiTmpData可以获取到原始字段值以及处理这个值所需要的运行算法名称。需要注意的是,如果是既要加密又要脱敏,则先执行脱敏再执行加密。如果既要解密又要脱敏,则先执行解密然后执行脱敏。
加解密默认算法(DataEncryptDef):
MD5/SHA256/HMACSHA256/RSA/AES/SM2/SM3/SM4
# 3.7.2 数据字段级脱敏操作
配置参数如下:
shanhai:
dataguard:
enable: true #启用组件
trace-log: true #启用跟踪日志
hyposensitRulesExt: #脱敏规则定义(需要自行扩展时才需要配置,默认不需要配置该扩展)
- {ruleId: 'yourRule',regex: '([1][1-9]\d{1})\d{4}(\d{4})',replacement: '$1****$2'}
注:此处的ruleId的值是示例,实际使用时自己可以改为其他标识字符串即可,regex为自定义正则,replacement为脱敏后的格式。使用的String.replaceAll做脱敏处理。
脱敏默认算法(DataHyposensitDef):
IDcard/RealName/TelPhone/email/money 分别对应的是:身份证/姓名/手机号/邮箱/金额
数据脱敏示例如下:
@ShanHaiDataGuard
public class DictData implements Serializable {
private static final long serialVersionUID = 1L;
@FieldDataGuard(ruleId = "dictLabel",hyposensit = true,hyposensitMethod = DataHyposensitDef.IDcard,hyposensitExecModel = DataExecModel.QUERY)
private String dictLabel;
}
# 3.7.3 使用自定义算法进行数据字段级加解密或脱敏操作
配置参数如下:
shanhai:
dataguard:
enable: true #启用组件
encryptRulesExt: #加密算法参数配置(自定义算法实现)
- {ruleId: 'xxxxx', ruleParams: {key: wjy59188wjy59188, iv: aaaaa1111, source: device}}
此处ruleParams内的参数你可以按照自己需要进行自定义,此处只是一个示例。
在自己的数据解析实现扩展加解密算法或者数据脱敏操作。
@Service
public class XXXDataGuardServiceImpl extends DefaultDataGuardServiceImpl {
@Autowired
private DataGuardConfig shanhaiDataGuardConfig;
public XXXDataGuardServiceImpl(DataGuardConfig shanhaiDataGuardConfig) {
super(shanhaiDataGuardConfig);
}
@Override
public String encrypt(ShanHaiTmpData shanHaiTmpData) {
//TODO 可以在此处扩展自定义加密算法实现
return super.encrypt(shanHaiTmpData);
}
@Override
public String decrypt(ShanHaiTmpData shanHaiTmpData) {
//TODO 可以在此处扩展自定义解密算法实现
return super.decrypt(shanHaiTmpData);
}
}
自己定义的加解密算法的配置参数可以从DataGuardConfig->encryptRulesExt->EncryptRule中获取,ruleParams在EncryptRule中以Map的形式存在。对于Domain对象中的ruleId以及原始字段数据可以从ShanHaiTmpData中获取。
对于脱敏,暂不支持配置自定义脱敏算法。需要实现的可以自己重写hyposensit的实现。
# 3.8基于序列化的响应报文数据脱敏
配置参数如下:
shanhai:
respguard:
enable: true #启用组件
trace-log: true #启用跟踪日志
# 3.8.1 基于规则ID定制字段级脱敏规则
在响应报文VO对象中需要进行脱敏的字段,添加注解 @RespFieldGuard并增加规则定义:
public class RespInfo {
@RespFieldGuard(ruleId = "text")
private String text;
}
实现RespGuardRuleDefService接口,实现自己的脱敏算法集合:
@Service
public class OpenRespGuardRuleDefService implements RespGuardRuleDefService {
@Override
public Object jsonGenerator(String ruleId, Object fieldValue) {
return String.valueOf(fieldValue)+"@"+ruleId;
}
}
注:此处只是做了通用性封装,没有内置任何脱敏算法,相关规则需要自己来实现。
# 3.8.2 基于目标类名和字段名实现全字段动态控制
在响应报文VO对象上添加注解 @RespDataGuard:
@RespDataGuard
public class RespInfo {
private String text;
}
实现RespGuardRuleDefService接口,实现自己的脱敏算法集合:
@Service
public class OpenRespGuardRuleDefService implements RespGuardRuleDefService {
@Override
public Object jsonDynamicGenerator(String tragetClass, Object tragetField, Object fieldValue) {
if(tragetField.equals("getMsg")){
return String.valueOf(fieldValue)+"@"+tragetClass+":"+tragetField;
}
//注意:对于不需要进行特殊处理的数据,需要在此返回正常对象值
return fieldValue;
}
}
注:此处只是做了通用性封装,没有内置任何脱敏算法,相关规则需要自己来实现。
RespDataGuard与RespFieldGuard两种不能同时存在,RespDataGuard优先级高,会优先进行序列化处理。
# 3.9通用响应报文编码组件
# 3.5.1 全量请求解码
配置参数如下
shanhai:
encodebody:
enable: true #启用组件
注:此组件只是做了通用性封装,对于编码逻辑需要自行实现接口EncodeBodyService的encodeRespBody方法,在进行数据编码时,会自动调用该接口的实现方法进行自定义参数编码操作。
接口定义如下:
/**
* 加密响应
* @param body 原始响应报文
* @return
*/
default String encodeRespBody(String body){
return body;
};
如果需要某个请求不进行解码操作,可以使用注解@EncodeBodyIgnore跳过对目标请求的解码操作。
# 3.5.2 指定请求解码
配置参数如下
shanhai:
encodebody:
enable: true #启用组件
mode: 2 #指定请求加密模式,默认为全量加密 mode:1
使用示例如下
@EncodeBody(ruleId = "demo")
public JSONObject encode(){
return "demoxx";
}
注:此组件只是做了通用性封装,对于编码逻辑需要自行实现接口EncodeBodyService的encodeRespBody方法,在进行数据编码时,会自动调用该接口的实现方法进行自定义参数编码操作。
接口定义如下:
/**
* 按照自定义规则ID加密响应报文
* @param ruleId 规则ID
* @param body 原始报文
* @return
*/
default String encodeRespBody(String ruleId,String body)
用户根据ruleId进行个性化编码组件开发。
# 3.10 敏感词检测过滤组件
配置参数如下
shanhai:
sensitivewords:
enable: true
sensitive-filter-mode: 1 #敏感词过滤模式 (1:自动脱敏放行 2:拒绝执行)
path-patterns: #敏感词检测范围
- '/*'
sensitive-words: "今天, 今天很好, 今天真烦" #敏感词清单(多个以英文,分隔)
task-enable: true #是否启用定时更新敏感词词库任务
task-inteval-period: 60 #定时更新频率 (单位:秒,默认值:600s)
山海Guard敏感词检测组件使用DFA算法对敏感词进行检测,支持通过配置文件进行敏感词配置,同时支持定时更新敏感词词库配置能力。
如果启用定时更新敏感词词库任务,则需要自行实现如下接口,动态加载敏感词数据:
public interface SensitiveWordsDictService {
public Set<String> loadDict();
}
# 3.11 数据操作审计插件
配置参数如下
shanhai:
dataaudit:
enable: true
#忽略的列
ignored-table-columns: TABLE_NAME1.COLUMN1
ignored-table-columns参数说明:
忽略的列,多个表用分号分隔,例如:TABLE_NAME1.COLUMN1,COLUMN2; TABLE2.COLUMN1,COLUMN2; TABLE3.*; *.COLUMN1,COLUMN2
TABLE_NAME1.COLUMN1,COLUMN2 : 表示忽略这个表的这2个字段
TABLE3.*: 表示忽略这张表的INSERT/UPDATE,delete暂时还保留
*.COLUMN1,COLUMN2:表示所有表的这个2个字段名都忽略
启用插件后想,需要自行实现如下接口,获取数据变更记录:
public interface ShanHaiDataAuditService {
public void dealOperationResult(OperationResult operationResult);
}
# 4 常见问题
# 4.1 文件上传检测不生效
在springboot中使用多个继承WebMvcConfigurationSupport的类是行不通的,而且使用注解@configuration去加载配置类只能挂载一个继承WebMvcConfigurationSupport。
解决办法:自己项目中的webmvc配置要实现 webMvcConfigurer 接口而不能使用继承WebMvcConfigurationSupport类的方式,这样组件和自己项目中的webmvc都可以挂载。
示例如下:
@Configuration
public class XXXConfig implements WebMvcConfigurer {
}
# 4.2基于Mybatis-Plus进行字段级加解密插件不生效解决方案
自定义实现数据源的时候(SqlSessionFactoryBean)这个时候在属性文件上的一些配置,包括单独配置 MybatisPlusConfig 已经不起作用了,这个时候,因为自定义的数据源,则在该数据源下添加插件配置:
//注入数据保护插件
@Autowired
private ShanHaiDataParameterInterceptor shanHaiDataParameterInterceptor;
@Autowired
private ShanHaiDataResultsInterceptor shanHaiDataResultsInterceptor;
//自定义数据源
@Bean(name = "primarySqlSessionFactory")
public SqlSessionFactory primarySqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource)
throws Exception {
MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
//Mysql分页插件示例(一般自定义数据源也要这样配置plus插件)
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
bean.setPlugins(interceptor);
//添加山海数据保护插件
bean.setPlugins(shanHaiDataParameterInterceptor);
bean.setPlugins(shanHaiDataResultsInterceptor);
return bean.getObject();
}
# 4.3 通用响应报文编码组件日期格式化异常
在对应字段添加如下注解,自行指定日志格式:
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
# 4.4 数据加解密插件与审计插件使用建议
数据操作尽可能职能单一化,不要在一个API内部通过递归方式频繁查询数据库数据。
举例说明:
查询一个机构的组织树,通过数据库递归方式动态构建树形结构,一般数据量不大的时候,不启用任何插件的情况下,执行时间一般都将近1s左右。启用插件的情况下,每递归一次假设有10ms的系能损失,递归次数多了,也会造成大量的数据时延。