Statement安全漏洞(sql注入問題)
問題展示:
首先我的Mysql數據庫中有一張users表,如下圖所示

/**
* 根據用戶名查詢用戶
* @param username 需要查詢的用戶名
* @return User 記錄對應的JavaBean對象
*/
public static User find(String name){
Connection conn = null;
Statement sta = null;
ResultSet re = null;
User user = null;
try{
//獲取JavaApp與Mysql數據的連接
conn = JDBCUtils.getConnection();
//創建封裝SQL語句的對象
sta = conn.createStatement();
//執行sql語句返回結果集合'or true or'
String sql = "select id,username,password,email,Date from users where username='"+ name + "'";
re = sta.executeQuery(sql);
while(re.next()){
int id = re.getInt("id");
String username = re.getString("username");
String password = re.getString("password");
String email = re.getString("email");
Date d = re.getDate("Date");
user = new User(id,username,password,email,d);
}
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException("根據用戶名查詢失敗");
}finally{
JDBCUtils.close(re);
JDBCUtils.close(sta);
JDBCUtils.close(conn);
}
return user;
}
public static void main(String[] args) {
//我們查找的是表中已有的數據李四
User user = Demo2_find.find("李四");
System.out.println(user == null ? "查無此人" : "查有此人");
}
運行上面這段代碼,程序返回的結果是李四在Mysql數據庫確實存在
,為了驗證測試效果,
這一次,我將上圖中標紅的部分User user = Demo2_find.find("李四");改為查找王五這個人,大家都知道王五這個人在數據庫是不存在的.這次運行的結果為
進一步證明,上面的代碼是沒有問題的,這是我依舊將標紅部分的代碼改掉,改成User user = Demo2_find.find("'or true or'");這時會發生什么神奇的效果呢?我們運行代碼看一下.

為了讓大家看的清楚一點,我將整張屏幕截取了下來
我們可以發現,當我們輸入'or true or'進行查詢的時候竟然通過了,能夠查詢到Mysql中的數據.
這就是著名的sql注入問題.
產生原因:
因為SQL語句拼接,傳入了SQL語句的關鍵字,繞過了安全檢查.
客戶端利用JDBC-【Statement】的缺點,傳入非法的參數,從而讓JDBC返回不合法的值,我們將這種情況下,統稱為SQL注入。
解決方案:
使用PreparedStatement對象就可以解決。PreparedStatement對象預處理對象。允許使用占位符對SQL語句中的變量進行占位。對SQL語句進行預先編譯。傳入SQL語句的關鍵字,不會被當成關鍵字而是普通的字符串。包括:程序執行時動態為?符號設置值,安全檢查,避免SQL注入問題,預處理能力
select * from user where username = ? and password = ?
Statement與PreparedStatement的區別
現在項目中都不直接用Statement了,而用PreparedStatement。
PreparedStatement它除了具有Statement是所有功能外,
還有動態SQL處理能力,包括:程序執行時動態為?符號設置值,安全檢查,避免SQL注入問題,預處理能力。
Statement只能處理靜態SQL
1,PreparedStatement既能處理靜態SQL,又能處理動態SQL,它繼承了Statement的特點
2,站在預處理這個角度來說的:
PreparedStatement【適合】做連續多次相同結構的SQL語句,有優勢。
Statement【適合】做連續多次不相同結構的SQL語句,有優勢。
適合:是只效率會更高,但並不表示一定要這才樣
3,PreparedStatement
1_支持動態SQL,也支持靜態SQL
2_預處理
---相同結構的SQL
select id,name from users where id = 1
select id,name,gender from users where id = 2;
是不相同結構
---不同結構的SQL
聲明:
靜態SQL也可以用PreparedStatement
適合:
靜態SQL---優先Statement

