PrepareStatement 防止sql注入

sql注入

經過把SQL命令插入到Web表單遞交或輸入域名或頁面請求的查詢字符串,最終達到欺騙服務器執行惡意的SQL命令java

危害:數據庫信息泄露mysql

惡意字符:1 or 1='1'等web


案例:sql

package com.zhiwei.database;
import java.sql.*;
public class PrepareStatementTest {

	public static void main(String[] args) {
		
		PreparedStatement ps =null;
		ResultSet rs=null;
		Connection ct=null;
		
			try {
				Class.forName("com.mysql.jdbc.Driver");
				ct = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test","squirrel","xiaoyang");
				ps=ct.prepareStatement("select *from user where name='zhangsan' and '1' or 1='1'");
				rs=ps.executeQuery();
				while(rs.next()){
					int id =rs.getInt(1); 
				    String name = rs.getString(2);
				    String passwd = rs.getString(3);
				    int age=rs.getInt(4);
				    String sex=rs.getString(5);
				    System.out.println(id+"--"+name+"--"+passwd+"--"+age+"--"+sex);
				}
			
			} catch (Exception e) {
				e.printStackTrace();
			} finally{
				try {
					if(rs!=null){
						rs.close();
					}if(ps!=null){
						ps.close();
					}if(ct!=null){
						ct.close();
					}
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
	}
}

控制檯日誌:數據庫

1--zhangsan--zhangsan--10--F
2--lisi--lisi--20--M
3--wangwu--wangwu--15--M
4--maliu--maliu--13--F
5--tianqi--tianqi--18--M
6--maba--maba--19--F
22--BBBB--BBBB--16--M

數據庫記錄:服務器

這裏寫圖片描述

結果:優化

sql語句沒有查出咱們想要的數據記錄,而是將全部的表的記錄都查詢出來了,形成數據泄露(典型的sql注入漏洞)ui

分析日誌

select *from user where name='zhangsan' and '1' or 1='1'code

sql語句中and的優先級高於or的優先級,所以 select *from user where name='zhangsan' and '1' or 1='1' 等價於: select *from user where (name='zhangsan' and '1') or 1='1' 因name='zhangsan' and '1' or 1='1'的最終結果都是爲真,where條件就失去做用,整條sql的功能等價於:select *from user

sql優化語句

select *from user where name='zhangsan' and ('1' or 1='1')

分析

將惡意sql字符隔開,根據()的優先級大於and,所以整個sql語句的判斷條件就變成name='zhangsan'和('1' or 1='1'),而('1' or 1='1')永久爲真,所以整條語句就實現了對name的過濾做用,惡意sql則變得多餘,但這樣的sql並無實際的使用價值


sql注入的解決方案

  • 使用PrepareStatement類的set方法,它在sql預編譯的時候對sql語句進行轉義,PrepareState過濾特定的字符將「乾淨」的二進制文件提交給數據庫,於是就達不到欺騙數據庫的效果 ps=ct.prepareStatement("select *from user where name=?"); ps.setString(1, "zhangsan and 1 or 1='1'"); rs=ps.executeQuery();
  • web項目中通常使用過濾器或者攔截器去過濾頁面表單傳過來的字符,拼接"乾淨"的sql語句再提交數據庫執行

注意:Mybatis中 $ 只是簡單的變量替換存在sql注入風向, # 會將sql語句預編譯,防止sql注入

相關文章
相關標籤/搜索