SQL注入:(查詢的百度解釋如下)
- 所謂SQL注入,就是通過把SQL命令插入到Web表單提交或輸入域名或頁面請求的查詢字符串,最終達到欺騙服務器執行惡意的SQL命令。具體來說,它是利用現有應用程序,將(惡意的)SQL命令注入到後臺數據庫引擎執行的能力,它可以通過在Web表單中輸入(惡意)SQL語句得到一個存在安全漏洞的網站上的數據庫,而不是按照設計者意圖去執行SQL語句。比如先前的很多影視網站泄露VIP會員密碼大多就是通過WEB表單遞交查詢字符暴出的,這類表單特別容易受到SQL注入式攻擊。
沿用上一篇博客中講到的使用工具類來連接數據庫
需求:請用戶輸入想要查詢的姓名,並顯示結果
這是users表的數據
代碼如下:
import com.studycode.utils.JDBCUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
public class Demo02 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
//1.獲取數據庫連接
connection = JDBCUtils.getConnection();
//2.創建statement對象
statement = connection.createStatement();
//3.編寫Sql語句
System.out.print("請輸入你要查詢的用戶名:");
String username = scanner.nextLine();
String sql = "select * from users where name = " + username;
System.out.println(sql);
resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.println(resultSet.getString("name"));
System.out.println(resultSet.getString("password"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//5.釋放資源
JDBCUtils.closeAll(resultSet,statement,connection);
}
}
}
代碼看起來是沒有問題的,思路也正確,但其實這樣的代碼是有問題的,以爲在編寫sql語句的時候採用了字符串拼接的形式,因此也就造成了漏洞…
- 可以看到這是輸入姓名爲:java,因爲users表中沒有java這個名字,因此沒有返回任何信息
根據之前學到的數據庫基礎知識,有與或非判斷條件,因此可以採用此方式繞過檢查以得到想要查詢的信息,如下:
可以看到,當輸入了’java’ or 1=1可以使用or語句的判斷機制來繞過檢查,這種方式稱之爲 SQL注入
可以採用prepareStatement類來代替Statement類解決sql注入問題
- PreperedStatement是Statement的子類
- 它的實例對象可以通過調用Connection.preparedStatement()方法獲得,相對於Statement對象而言:PreperedStatement可以避免SQL注入的問題。
preparedStatement【推薦使用】 和 Statement的異同;
- 相同點 : 都是用來執行sql語句的
- 不同點 :
1.Statement 不安全,會使數據庫頻繁編譯SQL,不能預編譯,不能使用佔位符,容易造成SQL語句拼接錯誤
2.preparedStatement 安全,預編譯SQL語句,可以使用 ? 佔位符,SQL更清晰。
3.Statement 先寫SQL語句再執行; Statement.execute(SQL)
4.preparedStatement 直接編譯SQL(使用?作爲佔位符),設置佔位符的數據,調用方法執行 preparedStatement.execute();
可將上面代碼優化如下:
import com.studycode.utils.JDBCUtils;
import java.sql.*;
import java.util.Scanner;
//防止SQL注入
public class Demo03 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//1.獲取數據庫連接
connection = JDBCUtils.getConnection();
System.out.print("請輸入你要查詢的用戶名:");
String username = scanner.nextLine();
//2.創建preparedStatement對象
preparedStatement = connection.prepareStatement("select * from users where name = ?");
preparedStatement.setString(1,username);
resultSet = preparedStatement.executeQuery();
while (resultSet.next()){
System.out.println(resultSet.getString("name"));
System.out.println(resultSet.getString("password"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//5.釋放資源
JDBCUtils.closeAll(resultSet,preparedStatement,connection);
}
}
}
再次測試:
可以發現,SQL注入的問題得到了解決。