mybatis的#{}和${}的區別以及order by注入問題

#{}至關於jdbc中的preparedstatementmysql

${}是輸出變量的值sql

你可能說不明因此,沒關係咱們看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"));
  }
輸出結果:

com.mysql.jdbc.PreparedStatement@1fa1ba1: select * from admin_domain_location order by 'domain_id'
4
2

這是個jdbc的preparedstatement例子,不要吐槽我這麼寫是否合法,這裏只是爲了說明問題.dom

以上例子有得出如下信息:code

1)order by後面若是採用預編譯的形式動態輸入參數,那麼實際插入的參數是一個字符串,例子中是:order by 'domain_id'排序

2)輸出結果並無排序,從sql語句中的形式咱們也能夠推測出此sql語句根本也不合法(正常應該是 order by domain_id)字符串

修改以上代碼以下:get

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"));
}
輸出結果:

com.mysql.jdbc.PreparedStatement@1fa1ba1: select * from admin_domain_location order by domain_id
3
5

這次咱們直接把一個變量的值拼接sql語句,從結果能夠看出來:input

1)sql語句拼接正常io

2)查詢結果排序正常

你可能要問這和#{}與${}有什麼關係..

上面已經說過#{}至關於jdbc的preparedstatement,因此以上的第一個例子就至關於#{},那麼第二個例子就天然而然指的是${}的狀況.

你可能說思惟仍是有些凌亂,沒關係咱們來看第三個例子:

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"));
}

輸出結果都爲:
com.mysql.jdbc.PreparedStatement@12bf560: select * from admin_domain_location where domain_id='2'

這第三個例子說的是#{}和${}通用的問題,也就是說在此種狀況下#{}和${}是通用的,只不過須要些小的轉換.如例子中須要手動

拼接單引號 ' ' 到變量值的先後,確保sql語句正常.

簡單說#{}是通過預編譯的,是安全的,而${}是未通過預編譯的,僅僅是取變量的值,是非安全的,存在sql注入.

這裏先說一下只能${}的狀況,從咱們前面的例子中也能看出,order by是確定只能用${}了,用#{}會多個' '致使sql語句失效.此外還有一個like 語句後也須要用${},簡單想一下

就能明白.因爲${}僅僅是簡單的取值,因此之前sql注入的方法適用此處,若是咱們order by語句後用了${},那麼不作任何處理的時候是存在sql注入危險的.你說怎麼防止,那我只

能悲慘的告訴你,你得手動處理過濾一下輸入的內容,如判斷一下輸入的參數的長度是否正常(注入語句通常很長),更精確的過濾則能夠查詢一下輸入的參數是否在預期的參數集合中..

** P.S.:感謝藍蘿蔔blu!您的文章解決了個人問題!**

相關文章
相關標籤/搜索