mysql防注入原理_mybatis-plus sql注入原理(3.0.1)

  • Post author:
  • Post category:mysql


MP版本为3.0.1

sql注入原理

①,入口类 com.baomidou.mybatisplus.core.injector.AbstractSqlInjector ,重点是这个方法

public void inspectInject(MapperBuilderAssistant builderAssistant, Class> mapperClass) {

String className = mapperClass.toString();

Set mapperRegistryCache = GlobalConfigUtils.getMapperRegistryCache(builderAssistant.getConfiguration());

if (!mapperRegistryCache.contains(className)) {

List methodList = this.getMethodList();

Assert.notEmpty(methodList, “No effective injection method was found.”);

// 循环注入自定义方法,这里开始注入sql

methodList.forEach(m -> m.inject(builderAssistant, mapperClass));

mapperRegistryCache.add(className);

/**

* 初始化 SQL 解析

*/

if (GlobalConfigUtils.getGlobalConfig(builderAssistant.getConfiguration()).isSqlParserCache()) {

SqlParserHelper.initSqlParserInfoCache(mapperClass);

}

}

}

②,由AbstractMethod 的injectMappedStatement 方法完成具体的注入,

我们看到实际是有其实现类的一个个injectMappedStatement 来完成注入的

2574bcda1116d7cc1b369c492b29b499.png

③,这里我以DeleteById 为例

@Override

public MappedStatement injectMappedStatement(Class> mapperClass, Class> modelClass, TableInfo tableInfo) {

//得到待解析sql的模板

SqlMethod sqlMethod = SqlMethod.DELETE_BY_ID;

//利用语言驱动和配置信息,table元数据,和刚才得到的sql方法模板得到sqlSource

SqlSource sqlSource = languageDriver.createSqlSource(configuration, String.format(sqlMethod.getSql(),

tableInfo.getTableName(), tableInfo.getKeyColumn(), tableInfo.getKeyProperty()), modelClass);

//最后添加到mybatis的configuration里的mappedStatements中

return this.addDeleteMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource);

}

④,DELETE_BY_ID的模板如下

由此我们可以猜出,在tableInfo 中必须要能得出表名和该表主键

c47c3b31eddad433e9e40a186def03de.png

执行AbstractSqlInjector #inspectInject 的原理

我们可以在该方法的第一行打一个断点

6e1d1a3e380fde26ba3315b318e2d1b1.png

看我红框圈起来的部门,我们可以大致猜出,是spring容器在实例化组件时,在实例化组件后调用组件的初始化方法,而引起的一连串反应。

通过翻看源码,我大致解释一下

1,AbstractAutowireCapableBeanFactory调用组件的afterPropertiesSet方法,这个组件的beanName为userMapper,这是一个我定义的一个继承自BaseMapper的一个接口

186fa0bd7d123ae15697096d68a55a9e.png

2,不知怎么地,居然跑去调用 DaoSupport的afterPropertiesSet方法(知道的朋友欢迎留言)

cadd8aa0aee91c6f677a0c775f15dc10.png

3,然后调用到了其子类的MapperFactoryBean 的checkDaoConfig方法

重点是一行,这个configuration是继承自org.apache.ibatis.session.Configuration 的子类,是有mp自定义的一个类

configuration.addMapper(this.mapperInterface);

0f4088a11b24085e69d25d8e2fd1adde.png

4,接下来调用com.baomidou.mybatisplus.core.MybatisMapperRegistry的addMapper方法

断点停在了86行

9b2fe16c0c94b10a4ecdb6d1f280df2b.png

5,我们看这个parse方法

利用GlobalConfigUtils 得到ISqlInjector,然后调用其inspectInject方法

ae26f6131aa09d1dc11478a1d5fb73a6.png

6,我们看看mp是如何得到这个ISqlInjector的

public static ISqlInjector getSqlInjector(Configuration configuration) {

// fix #140

GlobalConfig globalConfiguration = getGlobalConfig(configuration);

//从配置里拿,如果有,则用配置的

ISqlInjector sqlInjector = globalConfiguration.getSqlInjector();

if (sqlInjector == null) {

//没有配置,默认给一个DefaultSqlInjector

sqlInjector = new DefaultSqlInjector();

globalConfiguration.setSqlInjector(sqlInjector);

}

return sqlInjector;

}

7,而 DefaultSqlInjector 是继承自 AbstractSqlInjector 类的

由于DefaultSqlInjector没有重写AbstractSqlInjector的inspectInject方法,

所以DefaultSqlInjector在调用inspectInject方法时,实际上会用父类AbstractSqlInjector的inspectInject方法。



版权声明:本文为weixin_36282704原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。