Hibernate防止SQL注入

若是在查詢字段中輸入單引號"'",則會報錯,這是由於輸入的單引號和其餘的sql組合在一塊兒編程了一個新的sql,實際上這就是SQL注入漏洞,後來我在前臺和後臺都對輸入的字符進行了判斷。sql

 

永遠也不要寫這樣的代碼:數據庫

     String queryString = "from Item i where i.description like '" + searchString + "'";
     List result = session.createQuery(queryString).list();編程

    若是用戶輸入:foo' and callSomeStoredProcedure() and 'bar' = 'bar,則你的程序在執行一個簡單查詢後,還會調用某個存儲過程,安全

這樣你的程序就開了一個安全漏洞,若是用戶偶爾輸入了一個單引號,你的程序就可能報錯。session

 

永遠也不要把未經檢查的用戶輸入的值直接傳給數據庫!spa

幸運的時有一個簡單的機制能夠避免這種錯誤:對象

JDBC在綁定參數時有一個安全機制,它能夠準確的將那些須要轉義的字符進行轉義(escape),接口

如上面的searchString,它被escape,再也不做爲一個控制字符了,而是做爲被查詢的匹配的字符串的一部分。(這裏指的是prepared statement,而是用普通的statment不行,我試過)。ip

另外,若是咱們使用參數綁定,還能夠提升數據庫的執行效率,prepared statement語句被編譯一次後,被放在cache中,就再也不須要編譯,能夠提升效率。字符串

參數綁定有2種辦法:使用positional parameter或者named parameter。

Hibernate支持JDBC樣式的positional parameter(查詢字符串中使用?),它同使用named parameter的效果同樣(查詢字符串中使用:)。

使用named parameter

使用named parameter,咱們從新寫上面的查詢語句:

String queryString = "from Item item where item.description like :searchString";

冒號後面是一個named parameter,咱們可使用Query接口將一個參數綁定到searchString參數上:

    List result = session.createQuery(queryString)
                      .setString("searchString", searchString)
                      .list();

由於searchString是一個用戶輸入的字符串,因此咱們使用Query的setString()方法進行參數綁定,這樣代碼更清晰,更安全,效率更好!

若是有多個參數須要被幫定,咱們這樣處理:

String queryString = "from Item item "
                           + "where item.description like :searchString "
                           + "and item.date > :minDate";
List result = session.createQuery(queryString)
                  .setString("searchString", searchString)
                   .setDate("minDate", minDate)
                  .list();

使用positional parameter

    若是你喜歡,也可使用positional parameter:

String queryString = "from Item item "
                           + "where item.description like ? "
                           + "and item.date > ?";
List result = session.createQuery(queryString)
                  .setString(0, searchString)
                  .setDate(1, minDate)
                  .list();

這段代碼可讀性強不如上面的強,並且可維護性差,若是咱們的查詢稍微改變一點,將第一個參數和第二個參數改變一下位置:

String queryString = "from Item item "
                            + "where item.date > ? "
                           + "and item.description like ?";

這樣咱們的代碼中涉及到位置的地方都要修改,因此咱們強烈建議使用named parameter方式進行參數綁定。

最後,在named parameter中可能有一個參數出現屢次的狀況,應該怎麼處理呢?

String userSearch = "from User u where u.username like :searchString"
                           + " or u.email like :searchString";
List result = session.createQuery(userSearch)
                  .setString("searchString", searchString)
                   .list();

不要使用

爲了防止SQL注入,避免使用拼湊SQL語句的方式!!!

 

在Hibernate+Spring中getHibernateTemplate()返回的對象能夠調用find(String queryString, Object value...Object value)來實現named parameter。好比:

        Date startTime = new Date(); 

        Date endTime = new Date(); 

      String queryString = "from SdmsRacalertLog as log wherelog.alertTime between :startTime and :endTime"

      return getHibernateTemplate().find(queryString, startTime, endTime); 

相關文章
相關標籤/搜索