JDBC中Statement的Sql注入問(wèn)題詳解
Statement的Sql注入問(wèn)題
sql注入攻擊指的是通過(guò)構(gòu)建特殊的輸入作為參數(shù)傳入web應(yīng)用程序,而這些輸入大都是sql語(yǔ)法里的一些組合,通過(guò)執(zhí)行sql語(yǔ)句進(jìn)而執(zhí)行攻擊者所要做的操作,其產(chǎn)生的主要原因在于應(yīng)用程序沒(méi)有細(xì)致地過(guò)濾用戶輸入的數(shù)據(jù),致使非法數(shù)據(jù)侵入系統(tǒng)。
我們通過(guò)一個(gè)用戶登錄的小案例來(lái)大致了解sql注入的情況:(Oracle數(shù)據(jù)庫(kù)環(huán)境)
首先準(zhǔn)備一張表t_user:

create table t_user( name varchar2(10) primary key, password varchar2(10) not null )
插入一些測(cè)試數(shù)據(jù):
insert into t_user(name,password) values('tom','123');
insert into t_user(name,password) values('mary','456');
commit;
所使用的數(shù)據(jù)庫(kù)驅(qū)動(dòng):ojdbc8.jar
用JDBC連接數(shù)據(jù)庫(kù),寫(xiě)一個(gè)登錄案例:
public class TestSqlInjection {
public static void main(String[] args) {
String driverClass = "oracle.jdbc.OracleDriver";
String url = "jdbc:oracle:thin:@127.0.0.1:1521:XE";
String user = "briup";
String password = "briup";
@SuppressWarnings("resource")
Scanner input = new Scanner(System.in);
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
Class.forName(driverClass);
conn = DriverManager.getConnection(url, user, password);
stmt = conn.createStatement();
System.out.println("請(qǐng)輸入用戶名:");
String uname = input.nextLine();
System.out.println("請(qǐng)輸入密碼:");
String upass = input.nextLine();
String sql = "SELECT name,password FROM t_user WHERE name='" + uname + "' AND password='" + upass + "'";
// uname xxx
// upass xxx' or '1'='1
rs = stmt.executeQuery(sql);
if (rs.next()) {
System.out.println("登錄成功");
// 這時(shí)候我們認(rèn)為用戶名和密碼都正確情況下查詢出來(lái)的用戶肯定只有一條
System.out.println("歡迎您," + uname);
} else {
System.err.println("用戶名或密碼錯(cuò)誤!");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
效果:

很顯然使用Statement的確產(chǎn)生了sql注入的問(wèn)題。
但是使用PreparedStatement可以有效解決這個(gè)問(wèn)題。
public class TestSqlInjection {
public static void main(String[] args) {
String driverClass = "oracle.jdbc.OracleDriver";
String url = "jdbc:oracle:thin:@127.0.0.1:1521:XE";
String user = "briup";
String password = "briup";
@SuppressWarnings("resource")
Scanner input = new Scanner(System.in);
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
Class.forName(driverClass);
conn = DriverManager.getConnection(url, user, password);
String sql = "SELECT name,password FROM t_user WHERE name=? AND password=?";
ps = conn.prepareStatement(sql);
//uname xxx
//upass xxx' or '1'='1
System.out.println("請(qǐng)輸入用戶名:");
String uname = input.nextLine();
ps.setString(1, uname);
System.out.println("請(qǐng)輸入密碼:");
String upass = input.nextLine();
ps.setString(2, upass);
rs = ps.executeQuery();
if (rs.next()) {
System.out.println("登錄成功");
System.out.println("歡迎您," + uname);
} else {
System.err.println("用戶名或密碼錯(cuò)誤!");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
PreparedStatement 除了可以防止sql注入,在執(zhí)行大量重復(fù)性插入語(yǔ)句時(shí),也會(huì)明顯提升程序運(yùn)行的性能,同時(shí)避免了繁瑣的字符串拼接操作。
對(duì)比:
Statement ,是每次執(zhí)行一個(gè)sql語(yǔ)句,就要把一個(gè)完成的sql語(yǔ)句發(fā)送給數(shù)據(jù)庫(kù)進(jìn)行執(zhí)行,然后取回返回的結(jié)果。
PreparedStatement ,可以把一個(gè)sql語(yǔ)句的結(jié)構(gòu),提前發(fā)送給數(shù)據(jù)庫(kù)進(jìn)行預(yù)處理,然后在專門(mén)給發(fā)送要操作的具體的值,在數(shù)據(jù)量大的時(shí)候,這種方式會(huì)大大提高執(zhí)行效率。
到此這篇關(guān)于JDBC中Statement的Sql注入問(wèn)題詳解的文章就介紹到這了,更多相關(guān)Statement的Sql注入問(wèn)題內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IntelliJ IDEA配置Maven阿里云鏡像加速源的全流程
國(guó)內(nèi)網(wǎng)絡(luò)訪問(wèn) Maven 中央倉(cāng)庫(kù)經(jīng)常超時(shí)、依賴下載極慢或失敗,配置阿里云等國(guó)內(nèi)鏡像后,Java 項(xiàng)目依賴下載飛快,極大提升開(kāi)發(fā)效率,是中國(guó)開(kāi)發(fā)者必做優(yōu)化,本文就給大家介紹了IntelliJ IDEA配置Maven阿里云鏡像加速源的全流程,需要的朋友可以參考下2025-09-09
SpringBoot請(qǐng)求處理之常用參數(shù)注解介紹與源碼分析
SpringBoot是一種整合Spring技術(shù)棧的方式(或者說(shuō)是框架),同時(shí)也是簡(jiǎn)化Spring的一種快速開(kāi)發(fā)的腳手架,本篇讓我們一起學(xué)習(xí)請(qǐng)求處理、常用注解和方法參數(shù)的小技巧2022-10-10
使用lombok@Data存在extends時(shí)需要注意的問(wèn)題
在Java編程中,正確實(shí)現(xiàn)equals方法是保證對(duì)象比較一致性的關(guān)鍵,使用instanceof檢查類型可能導(dǎo)致違反對(duì)稱性原則,即當(dāng)子類和父類都重寫(xiě)equals時(shí)可能出現(xiàn)a.equals(b)不等于b.equals(a)的情況,Lombok的@EqualsAndHashCode注解可以通過(guò)callSuper=true參數(shù)2024-10-10
java實(shí)現(xiàn)掃雷游戲控制臺(tái)版
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)掃雷游戲控制臺(tái)版,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04

