1. 程式人生 > >[Js-JDBC]SQL註入及解決,Statement與PreparedStatement

[Js-JDBC]SQL註入及解決,Statement與PreparedStatement

接收 現象 dsta ets 字符 如何 sel 單引號 con

SQL註入的含義

用戶在輸入信息中有SQL關鍵字並且參與SQL語句的編譯,導致SQL語句含義扭曲,這種現象被稱為SQL註入

例如:

1 // 在登錄驗證的時候使用如下語句
2 String sql = 
"select * from tb_user where username = ‘"+username+"‘ and userpwd = ‘+pwd+‘";

而用戶在密碼處輸入:asd‘ or ‘a‘=‘a

則會導致

select * from tb_user where username = ‘admin‘ and userpwd = ‘asd‘ or ‘a‘=‘a‘;

顯而易見以上SQL語句條件永遠為真

根本原因:先拼接SQL語句字符串,然後再進行比那一,這個時候用戶提供的信息中含有SQL關鍵字,並參與了這次編譯,扭曲了原意

如何防止SQL註入

先定義SQL語句框架,對SQl語句進行預先編譯,只編譯一次,然後再去接收用戶提供的信息,用戶提供的信息中即使含有SQL語句的關鍵字,這些關鍵字不參與這次SQL語句的編譯,從而起不到作用,采用這種方式可以解決SQL註入問題

使用 PreparedStatement 代替 Statement 預編譯SQL語句,然後再傳入參數

註意:

有的系統是需要SQL註入的,比如 select * from where,這就需要使用 Statement

有的系統是要防止SQL註入的,比如登錄系統,所以使用 PreparedStatement

PreparedStatement 與 Statement 對比

  1. PreparedStatement 防止 SQL 註入 ,執行效率高
  2. SQL 語句對於 Statement 來說是:編譯一次執行一次;SQL 語句對於 PreparedStatement 是編譯一次執行 N 次
  3. PreparedStatement 是類型安全的,編譯期檢查傳入參數類型

註意:

使用 PreparedStatement 時 SQL 語句中的”?“不能寫在單引號中,否則無法識別,如下的句子是錯誤的

1 String sql = "select ename from emp where ename like ‘%?%‘";
2 PreparedStatement ps = conn.prepareStatement(sql); 3 ps.setString(1, "0");

正確的應該為:

1 String sql = "select ename from emp where ename like ?";
2 PreparedStatement ps = conn.prepareStatement(sql);
3 ps.setString(1, "%0%");

則會導致

[Js-JDBC]SQL註入及解決,Statement與PreparedStatement