ibatis动态传入表名造成的SQL注入的解决方案(摘录的)
如何解决动态数据表名,动态字段名情况下,由
ibatis
缓存
select
字段而引起的
字段找不到的情况?以下是最简单的解决办法!
当使用动态表,动态字段时,会引起字段名的缓存,以下是解决办法。
先看一个例子。下面是段
SQL
语句
<!--
根据查询条件从类推数据表中查询数据
-->
<select
id="select_resData_bycondition"
parameterClass="java.util.HashMap"
resultClass="java.util.HashMap" remapResults="true" >
select $fieldnames$ from $resourcetable$ where 1=1
<include refid="select_data_by_condition" />
</select>
前台传入的
hashmap
变量中,有动态数据表名,及字段名,
Dao
里面的调用方法如下:
//
根据动态数据表名及动态选择的字段按条件分页查出相应的数据
,
注意清除缓存的使
用
public void getResDataByCondition(Page page) {
// TODO Auto-generated method stub
super
.queryForListPagination("select_resData_bycondition",
page);
}
父类的
queryForListPagination
如下:其中
page
这个变量是对
dataset
进行一些
封装,对查询条件封装。
public
void
queryForListPagination(String
statementName,Page
page){
…
.
略
}
由于多个菜单会调用到这个
dao
中的
getResDataByCondition
方法,也就去调用
Id
为
select_resData_bycondition
的
select
语句,由于
ibatis
的缓存机制,
当第一次调用这个
select
语句时,会将字段查询出来,放入缓存中,比如第一个表
是
user
人员表,有字段
gh,name,gz
等字段,则第二次调用时,前台传入了表名是
Dwbm
部门表,有字段
bmbm,bmmc
等,看了
ibatis
的源码,知道
ibaits
中缓存列名的地方在这里:
com.ibatis.sqlmap.engine.mapping.result .AutoResultMap
public
synchronized
Object[]
getResults(StatementScope
statementScope, ResultSet rs)
throws SQLException {
if (allowRemapping || getResultMappings() == null) {
initialize(rs);
}
return super
.getResults(statementScope, rs);
}
所以第二次形成的正确
SQL
语句应该是
select bmbm,bmmc from
Dwbm where
条件
…
如果这样,当然能找到适合的数据,不过由于以上所述缓存机制的存在,使得
在执行第二个动态查询时,实际上先将上一次查询出来的字段名放在缓存中,
即
gh,name,gz
这时取出来,形成了实际的
SQL
语句
Select gh,name,gz from dwbm where
条件
这样当然就不正确了!
最简单的解决办法是在各
SQL
语句的书写中,加上
remapResults="true"
如上面的
id
为
"select_resData_bycondition"
的语句,
这样就强制每次根据前台传进的动态数据表名,和动态字段名,
重新去映射字段,而不再使用上一次的字段列表,这样当然就正确了!
再不会出现某字段找不到的情况!这是最简单的办法!