mysql order by sql注入_mybatis中#{}和${}的区别及order by的sql注入问题
前言略,直奔主題..
#{}相當(dāng)于jdbc中的preparedstatement
${}是輸出變量的值
簡(jiǎn)單的說(shuō)就是#{}傳過(guò)來(lái)的參數(shù)帶單引號(hào)'',而${}傳過(guò)來(lái)的參數(shù)不帶單引號(hào)。
你可能說(shuō)不明所以,不要緊我們看2段代碼:
String sql = "select * from admin_domain_location order by ?";
PreparedStatement st = con.prepareStatement(sql);
st.setString(1, "domain_id");
System.out.println(st.toString());
ResultSet rs = st.executeQuery();
while(rs.next()){
System.out.println(rs.getString("domain_id"));
}
輸出結(jié)果:
com.mysql.jdbc.PreparedStatement@1fa1ba1: select * from admin_domain_location?order by?'domain_id'
3
4
5
2
6
這是個(gè)jdbc的preparedstatement例子,不要吐槽我這么寫是否合法,這里只是為了說(shuō)明問(wèn)題.
以上例子有得出以下信息:?1)?order by后面如果采用預(yù)編譯的形式動(dòng)態(tài)輸入?yún)?shù),那么實(shí)際插入的參數(shù)是一個(gè)字符串,例子中是:order by??'domain_id'
2)輸出結(jié)果并沒(méi)有排序,從sql語(yǔ)句中的形式我們也可以推測(cè)出此sql語(yǔ)句根本也不合法(正常應(yīng)該是 order by?domain_id?)
修改以上代碼如下:
String input = "domain_id";
String sql = "select * from admin_domain_location order by "+input;
PreparedStatement st = con.prepareStatement(sql);
System.out.println(st.toString());
ResultSet rs = st.executeQuery();
while(rs.next()){
System.out.println(rs.getString("domain_id"));
}
輸出結(jié)果:
com.mysql.jdbc.PreparedStatement@1fa1ba1: select * from admin_domain_location?order by domain_id
2
3
4
5
6
此次我們直接把一個(gè)變量的值拼接sql語(yǔ)句,從結(jié)果可以看出來(lái):
1)sql語(yǔ)句拼接正常
2)查詢結(jié)果排序正常
你可能要問(wèn)這和#{}與${}有什么關(guān)系..
上面已經(jīng)說(shuō)過(guò)#{}相當(dāng)于jdbc的preparedstatement,所以以上的第一個(gè)例子就相當(dāng)于#{},那么第二個(gè)例子就自然而然指的是${}的情況.
你可能說(shuō)思維還是有些凌亂,不要緊我們來(lái)看第三個(gè)例子:
String sql = "select * from admin_domain_location where domain_id=?";
PreparedStatement st = con.prepareStatement(sql);
st.setString(1, "2");
System.out.println(st.toString());
ResultSet rs = st.executeQuery();
while(rs.next()){
System.out.println(rs.getString("domain_id"));
}
=======================================
String input = "2";
String sql = "select * from admin_domain_location where domain_id='"+input+"'";
PreparedStatement st = con.prepareStatement(sql);
System.out.println(st.toString());
ResultSet rs = st.executeQuery();
while(rs.next()){
System.out.println(rs.getString("domain_id"));
}
輸出結(jié)果都為:
com.mysql.jdbc.PreparedStatement@12bf560: select * from admin_domain_location where domain_id='2'
2
這第三個(gè)例子雖然說(shuō)的是#{}和${}通用的問(wèn)題,也就是說(shuō)在此種情況下#{}和${}是通用的,只不過(guò)需要些小的轉(zhuǎn)換.如例子中需要手動(dòng)
拼接單引號(hào) ' ' 到變量值的前后,確保sql語(yǔ)句正常.
簡(jiǎn)單說(shuō)#{}是經(jīng)過(guò)預(yù)編譯的,是安全的,而${}是未經(jīng)過(guò)預(yù)編譯的,僅僅是取變量的值,是非安全的,存在sql注入.
這里先說(shuō)一下只能${}的情況,從我們前面的例子中也能看出,order by是肯定只能用${}了,用#{}會(huì)多個(gè)' '導(dǎo)致sql語(yǔ)句失效.此外還有一個(gè)like 語(yǔ)句后也需要用${},簡(jiǎn)單想一下
就能明白.由于${}僅僅是簡(jiǎn)單的取值,所以以前sql注入的方法適用此處,如果我們order by語(yǔ)句后用了${},那么不做任何處理的時(shí)候是存在sql注入危險(xiǎn)的.你說(shuō)怎么防止,那我只
能悲慘的告訴你,你得手動(dòng)處理過(guò)濾一下輸入的內(nèi)容,如判斷一下輸入的參數(shù)的長(zhǎng)度是否正常(注入語(yǔ)句一般很長(zhǎng)),更精確寫查詢一下輸入的參數(shù)是否在預(yù)期的參數(shù)集合中..
總結(jié)
以上是生活随笔為你收集整理的mysql order by sql注入_mybatis中#{}和${}的区别及order by的sql注入问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 神都夜行录太素原晶怎么获得
- 下一篇: 南航将重新推出“随心飞”产品:不限年龄无