MyBatis-Plus防全表更新与删除插件BlockAttackInnerInterceptor
防全表更新与删除插件BlockAttackInnerInterceptor 是 MyBatis-Plus 框架提供的一个安全插件,专门用于防止恶意的全表更新和删除操作。该插件通过拦截 update 和 delete 语句,确保这些操作不会偶然中影响到整个数据表,从而保护数据的完备性和安全性。
功能特性
[*]阻止全表更新删除:插件能够识别并阻止没有指定条件的 update 和 delete 语句,这些语句可能会导致全表数据被修改或删除。
[*]保护数据安全:通过限制全表操作,减少因误操作或恶意攻击导致的数据丢失风险。
使用方法
[*]注入插件:在 Spring Boot 设置类中,通过 @Bean 注解将 MybatisPlusInterceptor 注入到 Spring 容器中,并添加 BlockAttackInnerInterceptor 作为内部拦截器。
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
return interceptor;
}
}
[*]设置拦截规则:插件默认拦截没有指定条件的 update 和 delete 语句。假如需要自定义拦截规则,可以参考 MyBatis-Plus 的文档进行设置。
测试示例
全表更新测试
以下测试示例展示了怎样使用 BlockAttackInnerInterceptor 来防止全表更新操作。
@SpringBootTest
public class QueryWrapperTest {
@Autowired
private UserService userService;
/**
* SQL:UPDATE userSET name=?,email=?;
*/
@Test
public void testFullUpdate() {
User user = new User();
user.setId(999L);
user.setName("custom_name");
user.setEmail("xxx@mail.com");
// 由于没有指定更新条件,插件将抛出异常
// com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Prohibition of table update operation
Assertions.assertThrows(MybatisPlusException.class, () -> {
userService.saveOrUpdate(user, null);
});
}
}
部门更新测试
以下测试示例展示了怎样正确地执行部门更新操作,插件不会对此类操作进行拦截。
@SpringBootTest
public class QueryWrapperTest {
@Autowired
private UserService userService;
/**
* SQL:UPDATE userSET name=?, email=? WHERE id = ?;
*/
@Test
public void testPartialUpdate() {
LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(User::getId, 1);
User user = new User();
user.setId(10L);
user.setName("custom_name");
user.setEmail("xxx@mail.com");
// 由于指定了更新条件,插件不会拦截此操作
userService.saveOrUpdate(user, wrapper);
}
}
注意
[*]合理设置:确保在设置插件时,思量到项目的实际需求,避免过度限制导致正常操作受阻。
[*]测试验证:在生产环境部署前,应充分测试插件的功能,确保其按预期工作。
BlockAttackInnerInterceptor 插件是 MyBatis-Plus 提供的一个重要的安全工具,它能够有效地防止全表更新和删除操作,保护数据库免受意外或恶意的数据破坏。通过合理设置和使用该插件,可以显着进步应用程序的数据安全性。
源码阅读
public class BlockAttackInnerInterceptor extends JsqlParserSupport implements InnerInterceptor {
@Override
public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
PluginUtils.MPStatementHandler handler = PluginUtils.mpStatementHandler(sh);
MappedStatement ms = handler.mappedStatement();
SqlCommandType sct = ms.getSqlCommandType();
if (sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
if (InterceptorIgnoreHelper.willIgnoreBlockAttack(ms.getId())) return;
BoundSql boundSql = handler.boundSql();
parserMulti(boundSql.getSql(), null);
}
}
@Override
protected void processDelete(Delete delete, int index, String sql, Object obj) {
this.checkWhere(delete.getTable().getName(), delete.getWhere(), "Prohibition of full table deletion");
}
@Override
protected void processUpdate(Update update, int index, String sql, Object obj) {
this.checkWhere(update.getTable().getName(), update.getWhere(), "Prohibition of table update operation");
}
protected void checkWhere(String tableName, Expression where, String ex) {
Assert.isFalse(this.fullMatch(where, this.getTableLogicField(tableName)), ex);
}
private boolean fullMatch(Expression where, String logicField) {
if (where == null) {
return true;
}
if (StringUtils.isNotBlank(logicField) && (where instanceof BinaryExpression)) {
BinaryExpression binaryExpression = (BinaryExpression) where;
if (StringUtils.equals(binaryExpression.getLeftExpression().toString(), logicField) || StringUtils.equals(binaryExpression.getRightExpression().toString(), logicField)) {
return true;
}
}
if (where instanceof EqualsTo) {
// example: 1=1
EqualsTo equalsTo = (EqualsTo) where;
return StringUtils.equals(equalsTo.getLeftExpression().toString(), equalsTo.getRightExpression().toString());
} else if (where instanceof NotEqualsTo) {
// example: 1 != 2
NotEqualsTo notEqualsTo = (NotEqualsTo) where;
return !StringUtils.equals(notEqualsTo.getLeftExpression().toString(), notEqualsTo.getRightExpression().toString());
} else if (where instanceof OrExpression) {
OrExpression orExpression = (OrExpression) where;
return fullMatch(orExpression.getLeftExpression(), logicField) || fullMatch(orExpression.getRightExpression(), logicField);
} else if (where instanceof AndExpression) {
AndExpression andExpression = (AndExpression) where;
return fullMatch(andExpression.getLeftExpression(), logicField) && fullMatch(andExpression.getRightExpression(), logicField);
} else if (where instanceof Parenthesis) {
// example: (1 = 1)
Parenthesis parenthesis = (Parenthesis) where;
return fullMatch(parenthesis.getExpression(), logicField);
}
return false;
}
/**
* 获取表名中的逻辑删除字段
*
* @param tableName 表名
* @return 逻辑删除字段
*/
private String getTableLogicField(String tableName) {
if (StringUtils.isBlank(tableName)) {
return StringUtils.EMPTY;
}
TableInfo tableInfo = TableInfoHelper.getTableInfo(tableName);
if (tableInfo == null || !tableInfo.isWithLogicDelete() || tableInfo.getLogicDeleteFieldInfo() == null) {
return StringUtils.EMPTY;
}
return tableInfo.getLogicDeleteFieldInfo().getColumn();
}
}
https://i-blog.csdnimg.cn/direct/14f2a1c7cde54a95bfe143c73ccb7c8d.png
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]