16-MySQL-JDBC-SQL注入問題及PreparedStatement物件
阿新 • • 發佈:2021-01-21
MySQL -> JDBC -> SQL注入問題、PreparedStatement物件
1. SQL注入問題
- sql存在漏洞,會被攻擊導致資料洩露;
- 本質:sql會被拼接 or
- 例項:
import com.anobabe.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SQLIn {
public static void main(String[] args) {
//login("ano","123456");
login("'or '1=1","'or '123456");
}
//登入業務
public static void login(String username,String password){
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
st = conn.createStatement();
//SELECT * FROM users WHERE `name`='ano' AND `password`='123456';
String sql = "SELECT * FROM users WHERE `name` = '" + username + "' AND `password`='" + password + "'";
rs = st.executeQuery(sql);
while (rs.next()){
System.out.println(rs.getString("name"));
System.out.println(rs.getString("password"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JdbcUtils.release(conn,st,rs);
}
}
}
2. PreparedStatement物件
- 預編譯
- 可以防止SQL注入
- 效率更高
增:
import com.anobabe.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.util.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestInsert {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pst = null;
try {
conn = JdbcUtils.getConnection();
// 與Statement的區別:使用?佔位符代表引數
String sql = "INSERT INTO users(`id`,`name`,`password`,`email`,`birthday`) VALUES (?,?,?,?,?)";
pst = conn.prepareStatement(sql);
pst.setInt(1,5);
pst.setString(2,"Jay");
pst.setString(3,"111111");
pst.setString(4,"[email protected]");
//注意點:java.sql.Date -- 資料庫
// java.util.Date -- Java new Date().getTime()獲得時間戳
pst.setDate(5,new java.sql.Date(new Date().getTime()));
//執行:預編譯執行不用穿引數
int i = pst.executeUpdate();
if(i>0){
System.out.println("插入成功!");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JdbcUtils.release(conn,pst,null);
}
}
}
刪:
import com.anobabe.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestDelete {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pst = null;
try {
conn = JdbcUtils.getConnection();
// 與Statement的區別:使用?佔位符代表引數
String sql = "DELETE FROM users WHERE id=?";
pst = conn.prepareStatement(sql);
pst.setInt(1,5);
//執行:預編譯執行不用穿引數
int i = pst.executeUpdate();
if(i>0){
System.out.println("刪除成功!");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JdbcUtils.release(conn,pst,null);
}
}
}
改:
import com.anobabe.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestUpdate {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pst = null;
try {
conn = JdbcUtils.getConnection();
// 與Statement的區別:使用?佔位符代表引數
String sql = "UPDATE users SET `name`=? WHERE id=?";
pst = conn.prepareStatement(sql);
pst.setString(1,"anobabe");
pst.setInt(2,2);
//執行:預編譯執行不用穿引數
int i = pst.executeUpdate();
if(i>0){
System.out.println("更新成功!");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JdbcUtils.release(conn,pst,null);
}
}
}
查:
import com.anobabe.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestSelect {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pst = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
String sql = "SELECT * FROM users WHERE id=?";
pst = conn.prepareStatement(sql);
pst.setInt(1,2);
rs = pst.executeQuery();
while (rs.next()){
System.out.println(rs.getInt("id"));
System.out.println(rs.getString("name"));
System.out.println(rs.getString("password"));
System.out.println(rs.getString("email"));
System.out.println(rs.getDate("birthday"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JdbcUtils.release(conn,pst,rs);
}
}
}
- PreparedStatement防止SQL注入
import com.anobabe.lesson02.utils.JdbcUtils;
import java.sql.*;
public class SQLIn {
public static void main(String[] args) {
//login("ano","123456");
login("' ' or 1=1","123456");
}
//登入業務
public static void login(String username,String password){
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
//SELECT * FROM users WHERE `name`='ano' AND `password`='123456';
String sql = "SELECT * FROM users WHERE `name` = ? AND `password`=?";
st = conn.prepareStatement(sql);
st.setString(1,username);
st.setString(2,password);
rs = st.executeQuery();
while (rs.next()){
System.out.println(rs.getString("name"));
System.out.println(rs.getString("password"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JdbcUtils.release(conn,st,rs);
}
}
}
執行結果:不報錯,但無結果
PreparedStatement防止SQL注入的本質:把傳遞進來的引數當作字元,假設其中存在轉義字元,就直接忽略