Java:PreparedStatement 防止SQL注入

Statement和PreparedStatement的區別

聯繫

  1. PreparedStatement繼承自Statement,兩者都是接口。
  2. Statement 用於執行靜態SQL 語句在執行時,必須指定一個事先準備好的SQL語句。
  3. PreparedStatement 是預編譯的SQL語句對象,sql語句被預編譯並保存在對象中。被封裝的sql語句代表某一類操作,語句可以包含動態的參數 “ ?”,執行時可以爲“ ? ”動態設置參數值。
  4. 使用PreparedStatement對象執行sql時,sql語句被數據庫進行解析和編譯,然後被放到命令緩存區,每當執行同一個PreparedStatement 對象時,它就會被解析一次,但不會被再次編譯。在緩存區可以發現預編譯的sql命令,並且可以重用。
  5. PreparedStatement 可以減少編譯次數提高數據庫性能。

防止SQL注入

方法一:創建Statement對象

例如:

1.Class.forName(com.mysql.jdbc.Driver);//加載驅動
2.Connection conn=DriverManager.getConnection("jdbc:mysql//:....")//創建與某個數據庫的連接
3.Statement stmt=conn.CreateStatement();//創建一個statementd對象
4.String id=01;
5.String sql="delete from table where id='"+id+"'";//構建SQL語句
6.stmt.executeUpdate(sql);//執行SQL語句

上面的這段代碼的本意是想刪除在數據庫裏刪除 id=01 的記錄,但是如果有人將 id 的內容改爲 " 01 or 1=1" 時,數據庫在接收到命令後,無論你輸入是否存在都會執行,因爲數據庫會把 " or 1=1"當成判斷條件,所以無論如何該語句都會執行。那麼表中的任何記錄都將被刪除,後果會非常嚴重。

缺點:

  • 不能防止sql 注入,安全性低
  • 每次執行都需要重新編譯sql語句,效率低下。

方法二:創建PreparedStatement對象

1.Class.forName(com.mysql.jdbc.Driver);//加載驅動
2.Connection conn=DriverManager.getConnection("jdbc:mysql//:....")//創建與某個數據庫的連接
3.String sql="delete from table where id=?";//構建SQL語句,設置佔位符
4.PreparedStatement ps=conn.PreparedStatement(sql);//創建PreparedStatement時傳入sql語句,實現預編譯
5.ps.setInt(1,"01");//設置sql語句的佔位符的值,注意第一個參數爲1
6.ps.executeUpdate();//執行SQL語句

爲什麼PreparedStatement能防止sql注入呢???

因爲sql 語句是預編譯的,而且語句中使用了佔位符,規定了sql語句的結構。並且如果輸入" 01 or 1=1"時,數據庫會把" 01 or 1=1"當成值,而不是"1=1" 當成判斷條件,所以能防止sql注入。

實際開發中,建議使用PreparedStatement訪問數據庫,因爲它不僅能防止sql注入,安全性提高;而且是預編譯的 ,不用每執行一次都需要重新編譯SQL語句,效率高;另外,它執行語句得到的結果是離線的,連接關閉後,仍然可以訪問結果集。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章