JDBC预处理对象prepareStatement
JDBC預(yù)處理對(duì)象prepareStatement概述
一、SQL注入問(wèn)題
SQL注入:用戶(hù)輸入的內(nèi)容作為了SQL語(yǔ)句語(yǔ)法的一部分,改變了原有SQL真正的意義。
假設(shè)有登錄案例SQL語(yǔ)句如下:
SELECT * FROM 用戶(hù)表 WHERE NAME = 用戶(hù)輸入的用戶(hù)名 AND PASSWORD = 用戶(hù)輸?shù)拿艽a;
此時(shí),當(dāng)用戶(hù)輸入正確的賬號(hào)與密碼后,查詢(xún)到了信息則讓用戶(hù)登錄。但是當(dāng)用戶(hù)輸入的賬號(hào)為XXX 密碼為:XXX’ OR ‘a(chǎn)’=’a時(shí),則真正執(zhí)行的代碼變?yōu)?#xff1a;
SELECT * FROM 用戶(hù)表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’ OR ’a’=’a’;
此時(shí),上述查詢(xún)語(yǔ)句時(shí)永遠(yuǎn)可以查詢(xún)出結(jié)果的。那么用戶(hù)就直接登錄成功了,顯然我們不希望看到這樣的結(jié)果,這便是SQL注入問(wèn)題。
為此,我們使用PreparedStatement來(lái)解決對(duì)應(yīng)的問(wèn)題。
二、代碼演示SQL注入問(wèn)題
(1)數(shù)據(jù)庫(kù)準(zhǔn)備
代碼如下:
#創(chuàng)建sql_into數(shù)據(jù)庫(kù) CREATE DATABASE sql_into; #使用sql_into數(shù)據(jù)庫(kù) USE sql_into; #創(chuàng)建sql_into用戶(hù)表 CREATE TABLE users(uid INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(200),PASSWORD VARCHAR(200) ); #加入用戶(hù)信息 INSERT INTO users(username,PASSWORD) VALUES('xiaoming','123'),('xiaoliang','456'); #查詢(xún)用戶(hù)信息 SELECT *FROM users;mysql代碼演示
(2)創(chuàng)建用戶(hù)登錄界面
public class StatementMyCode {public static void main(String[] args) throws SQLException {Scanner sc=new Scanner(System.in);System.out.println("請(qǐng)輸入用戶(hù)名:");String username =sc.nextLine();System.out.println("請(qǐng)輸入密碼:");String password=sc.nextLine(); //獲取JDBCUtils連接Connection con=JDBCUtils1.getConnection();//Connection con= JDBCUtils1.getConnection(); //獲取Statedment對(duì)象Statement stat=con.createStatement(); //執(zhí)行SQL語(yǔ)句String sql = "select * from users where username='"+username+"' and password ='"+password+"'";System.out.println(sql);ResultSet rs=stat.executeQuery(sql);if(rs.next()){System.out.println("登錄成功!");}else{System.out.println("登錄失敗!");}JDBCUtils1.close(rs,stat,con);} }SQL注入出現(xiàn)的登錄BUG
(3)配置文件代碼
配置文件代碼文件名需要和JDBCUtils1里的工具類(lèi)的配置文件保持一致,配置文件代碼文件名為config.properties
className=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/sql_into
user=root
password=root
(4)JDBCUtils1文件代碼
public class JDBCUtils1 {private static String url;private static String user;private static String password;private static String className;private JDBCUtils1(){}static {try{Properties p=new Properties();InputStream in = JDBCUtils1.class.getClassLoader().getResourceAsStream("config.properties");p.load(in);in.close();url=p.getProperty("url");user=p.getProperty("user");password=p.getProperty("password");className=p.getProperty("className");//注冊(cè)驅(qū)動(dòng)Class.forName(className);}catch (Exception e){e.printStackTrace();} }public static Connection getConnection(){//獲取連接Connection con=null;try {con= DriverManager.getConnection(url,user,password);return con;} catch (SQLException e) {throw new RuntimeException("連接失敗");}}public static void close(ResultSet rs, Statement stat,Connection con){try {if(rs!=null)rs.close();} catch (SQLException e) {e.printStackTrace();}try {if(stat!=null)stat.close();} catch (SQLException e) {e.printStackTrace();}try {if (con!=null)con.close();} catch (SQLException e) {e.printStackTrace();}} }三、防止SQL注入 使用預(yù)處理對(duì)象
(1)原理介紹
preparedStatement:預(yù)編譯對(duì)象,是Statement對(duì)象的子類(lèi)。
特點(diǎn):
- 性能高
- 會(huì)把sql語(yǔ)句先編譯
- 能過(guò)濾掉用戶(hù)輸入的關(guān)鍵字。
PreparedStatement預(yù)處理對(duì)象,處理的每條sql語(yǔ)句中所有的實(shí)際參數(shù),都必須使用占位符?替換。
PreparedStatement使用,需要通過(guò)以下3步驟完成:
// 獲得預(yù)處理對(duì)象,需要提供已經(jīng)使用占位符處理后的SQL語(yǔ)句
PreparedStatement psmt = conn.prepareStatement(sql)
void setXxx(int index, Xxx xx) 將指定參數(shù)設(shè)置指定類(lèi)型的值
參數(shù)1:index 實(shí)際參數(shù)序列號(hào),從1開(kāi)始。
參數(shù)2:xxx 實(shí)際參數(shù)值,xxx表示具體的類(lèi)型。
例如:
setString(2, “1234”) 把SQL語(yǔ)句中第2個(gè)位置的占位符?替換成實(shí)際參數(shù) “1234”
int executeUpdate(); --執(zhí)行insert update delete語(yǔ)句.
ResultSet executeQuery(); --執(zhí)行select語(yǔ)句.
boolean execute(); --執(zhí)行select返回true 執(zhí)行其他的語(yǔ)句返回false.
(2)使用preparedStatement
用戶(hù)登錄界面代碼演示
public class prepareStatementMyCode {public static void main(String[] args) throws SQLException {Scanner sc=new Scanner(System.in);System.out.println("請(qǐng)輸入用戶(hù)名:");String username =sc.nextLine();System.out.println("請(qǐng)輸入密碼:");String password=sc.nextLine(); //獲取JDBCUtils連接Connection con=JDBCUtils1.getConnection();//Connection con= JDBCUtils.getConnection(); //獲取Statedment對(duì)象Statement stat=con.createStatement(); //執(zhí)行SQL語(yǔ)句String sql = "select * from users where username=? and password =?";PreparedStatement ps = con.prepareStatement(sql);ps.setObject(1,username);ps.setObject(2,password);System.out.println(sql);ResultSet rs=ps.executeQuery();if(rs.next()){System.out.println("登錄成功!");}else{System.out.println("登錄失敗!");}JDBCUtils1.close(rs,stat,con);} }正確執(zhí)行代碼演示結(jié)果
SQL注入代碼演示
四、使用prepareStatement完成查詢(xún)數(shù)據(jù)
代碼如下:
public class prepareStatementCSDNSelect {public static void main(String[] args) {//獲取連接對(duì)象Connection con=null;PreparedStatement ps= null;ResultSet rs = null;try {con= JDBCUtils1.getConnection();String sql="select * from users";ps = con.prepareStatement(sql);rs = ps.executeQuery();while(rs.next()){int uid=rs.getInt("uid");String username=rs.getString("username");String password=rs.getString("password");System.out.println(uid+" "+username+" "+password);}} catch (SQLException e) {throw new RuntimeException(e);}finally {JDBCUtils1.close(rs,ps,con);}} }使用prepareStatement完成查詢(xún)
五、使用prepareStatement和javabean類(lèi)完成查詢(xún)
(1)創(chuàng)建user1類(lèi)
代碼如下:
/*一個(gè)類(lèi)具備私有成員變量 空參構(gòu)造方法 get/set 方法 實(shí)現(xiàn)序列化接口 那么稱(chēng)這個(gè)類(lèi)為javabean類(lèi)*/ public class User1 {private int uid;private String username;private String password;public User1() {}public User1(int uid, String username, String password) {this.uid = uid;this.username = username;this.password = password;}public int getUid() {return uid;}public void setUid(int uid) {this.uid = uid;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "User1{" +"uid=" + uid +", username='" + username + '\'' +", password='" + password + '\'' +'}';} }(2)使用把每條記錄封裝到user1對(duì)象中 將多個(gè)user1對(duì)象放到list集合當(dāng)中
/*查詢(xún)所有記錄 把每條記錄封裝到user1對(duì)象中 將多個(gè)user1對(duì)象放到list集合當(dāng)中*/ public class prepareStatementCSDNSelectBean {public static void main(String[] args) {//獲取連接對(duì)象Connection con=null;PreparedStatement ps= null;ResultSet rs = null;try {con= JDBCUtils1.getConnection();String sql="select * from users";ps = con.prepareStatement(sql);rs = ps.executeQuery();//定義一個(gè)集合用來(lái)存儲(chǔ)user對(duì)象List<User1> list=new ArrayList<>();while(rs.next()){int uid=rs.getInt("uid");String username=rs.getString("username");String password=rs.getString("password");User1 u=new User1(uid,username,password);list.add(u);// System.out.println(uid+" "+username+" "+password);}System.out.println(list);} catch (SQLException e) {throw new RuntimeException(e);}finally {JDBCUtils1.close(rs,ps,con);}} }查詢(xún)結(jié)果演示
總結(jié)
以上是生活随笔為你收集整理的JDBC预处理对象prepareStatement的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: (tomcat linux)
- 下一篇: 安卓邮箱设置 无法连接服务器(安卓邮箱设