欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文搞懂Java?JDBC中的SQL注入問(wèn)題

 更新時(shí)間:2022年10月27日 14:51:37   作者:樂(lè)趣國(guó)學(xué)  
在用戶輸入的數(shù)據(jù)中有SQL關(guān)鍵字或語(yǔ)法,并且關(guān)鍵字或語(yǔ)法參與了SQL語(yǔ)句的編譯,導(dǎo)致SQL語(yǔ)句編譯后的條件為true,一直得到正確的結(jié)果,這種現(xiàn)象就是SQL注入,這篇文章主要介紹了一文搞懂Java?JDBC中的SQL注入問(wèn)題,需要的朋友可以參考下

??SQL注入

?什么是SQL注入

在用戶輸入的數(shù)據(jù)中有SQL關(guān)鍵字或語(yǔ)法,并且關(guān)鍵字或語(yǔ)法參與了SQL語(yǔ)句的編譯。導(dǎo)致SQL語(yǔ)句編譯后的條件為true,一直得到正確的結(jié)果。這種現(xiàn)象就是SQL注入。

?SQL注入的效果的演示

??SQL注入代碼

package cn.bdqn.demo03;
?
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
?
public class Login {
?
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        
        //創(chuàng)建Scanner類對(duì)象,從控制臺(tái)獲取用戶名和密碼數(shù)據(jù)
        Scanner sc = new Scanner(System.in);
        System.out.println("請(qǐng)輸入用戶名:");
        String user = sc.nextLine();//使用nextLine()方法獲取字符串
        System.out.println("請(qǐng)輸入密碼:");
        String pwd = sc.nextLine();//使用nextLine()方法獲取字符串
        
        //1、注冊(cè)驅(qū)動(dòng)
        Class.forName("com.mysql.jdbc.Driver");
        //2、獲取連接對(duì)象
        String url = "jdbc:mysql://127.0.0.1:3306/java221804";
        String dbuser = "root";
        String pssword = "123456";
        Connection connection = DriverManager.getConnection(url, dbuser, pssword);
        //3、獲取發(fā)送SQL語(yǔ)句的對(duì)象
        Statement statement =connection.createStatement();
        //編寫(xiě)SQL語(yǔ)句
        String sql = "SELECT * FROM user WHERE username='"+user+"' AND pssword = '"+pwd+"';";
        //4、執(zhí)行SQL語(yǔ)句
        ResultSet resultSet=statement.executeQuery(sql);
        if(resultSet.next()){
            System.out.println("用戶名和密碼正確,登錄成功");
        }else{
            System.out.println("用戶名或密碼不正確,登錄失敗");
        }
        //6、關(guān)閉資源
        resultSet.close();
        statement.close();
        connection.close();
        sc.close();
    }
}

??SQL注入效果

輸入錯(cuò)誤的用戶名和密碼,提示登錄失?。?/p>

輸入錯(cuò)誤的用戶名和密碼,提示登錄成功:產(chǎn)生了SQL注入

上面案例代碼中,當(dāng)你的用戶名為 abc' or 1=1;# 密碼為123,拼接到SQL語(yǔ)句中,變成如下效果:

SELECT * FROM user WHERE username='abc' or 1=1;#' AND pssword = '123';

此SQL語(yǔ)句or 后面1=1永遠(yuǎn)正確,#后面的成了注釋,所以這條語(yǔ)句會(huì)將表中所有的數(shù)據(jù)查詢出來(lái),然后再做數(shù)據(jù)判斷的時(shí)候,就會(huì)得到正確結(jié)果,從而說(shuō)用戶名和密碼正確,登錄成功。

?如何避免SQL注入

使用PreparedStatement代替Statement可以有效防止SQL注入的發(fā)生。由于SQL注入產(chǎn)生的原因是在用戶輸入數(shù)據(jù)對(duì)SQL整合,整合后再發(fā)送到數(shù)據(jù)庫(kù)進(jìn)行編譯產(chǎn)生的。

所以為了避免SQL注入,就需要SQL語(yǔ)句在用戶輸入數(shù)據(jù)前就進(jìn)行編譯,成為完整的SQL語(yǔ)句,編譯完成后再進(jìn)行數(shù)據(jù)填充。這個(gè)操作需要使用PrepareStatement實(shí)現(xiàn)。

PreparedStatement利用預(yù)編譯的機(jī)制將sql語(yǔ)句的主干和參數(shù)分別傳輸給數(shù)據(jù)庫(kù)服務(wù)器,從而使數(shù)據(jù)庫(kù)分辨的出哪些是sql語(yǔ)句的主干哪些是參數(shù),這樣一來(lái)即使參數(shù)中帶了sql的關(guān)鍵字,數(shù)據(jù)庫(kù)服務(wù)器也僅僅將他當(dāng)作參數(shù)值使用,關(guān)鍵字不會(huì)起作用,從而從原理上防止了sql注入的問(wèn)題。

??PrepareStatement解決SQL注入

PreparedStatement接口繼承了Statement接口,執(zhí)行SQL語(yǔ)句的方法與Statement執(zhí)行SQL語(yǔ)句的方法相同。

?PreparedStatement的應(yīng)用

PreparedStatement的作用:

  • 預(yù)編譯SQL語(yǔ)句,效率高
  • 安全,避免SQL注入
  • 可以動(dòng)態(tài)的填充數(shù)據(jù),執(zhí)行多個(gè)同結(jié)構(gòu)的SQL語(yǔ)句

??參數(shù)標(biāo)記

//預(yù)編譯SQL語(yǔ)句,SQL中的所有參數(shù)由?符號(hào)占位,這被稱為參數(shù)標(biāo)記。在執(zhí)行SQL語(yǔ)句之前,必須為每個(gè)參數(shù)提供值。

String sql = "select * from user where userName = ? and pssword=?;";

PreparedStatement preparedStatement = connection.prepareStatement(sql);

??動(dòng)態(tài)參數(shù)綁定

preparedStatement.sexXxx(下標(biāo),值):參數(shù)下標(biāo)從1開(kāi)始,為指定參數(shù)下標(biāo)綁定值。Xxx表示數(shù)據(jù)類型。

//綁定參數(shù),有多少個(gè)?綁定多少個(gè)參數(shù)值

preparedStatement.setString(1, userName);

preparedStatement.setString(2, pwd);

?綜合案例

package cn.bdqn.demo02;
?
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;
?
public class PreparedStatementDemo01 {
?
    public static void main(String[] args) throws ClassNotFoundException,SQLException {
?
        Scanner sc = new Scanner(System.in);
        System.out.println("請(qǐng)輸入用戶名:");
        String userName = sc.nextLine();
        System.out.println("請(qǐng)輸入密碼:");
        String pwd = sc.nextLine();
?
        // 1、注冊(cè)驅(qū)動(dòng)
        Class.forName("com.mysql.jdbc.Driver");
        // 2、獲得連接
        String url = "jdbc:mysql://localhost:3306/java2217";
        String user = "root";
        String pssword = "123456";
        Connection connection = DriverManager.getConnection(url, user, pssword);
        // 3、獲取發(fā)送SQL對(duì)象
        String sql = "select * from user where userName = ? and pssword=?;";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        // 4、綁定參數(shù),有多少個(gè)?綁定多少個(gè)參數(shù)值
        preparedStatement.setString(1, userName);
        preparedStatement.setString(2, pwd);
        // 5、執(zhí)行SQL語(yǔ)句,并處理結(jié)果
        ResultSet resultSet = preparedStatement.executeQuery();
        if (resultSet.next()) {
            System.out.println("用戶名和密碼正確,登錄成功");
        } else {
            System.out.println("用戶名或密碼錯(cuò)誤,登錄失敗");
        }
        // 6、釋放資源:與關(guān)閉流的方式一樣,先開(kāi)的后關(guān),后開(kāi)的先關(guān)
        resultSet.close();
        preparedStatement.close();
        connection.close();
        sc.close();
    }
}

?PreparedStatement總結(jié)

PreparedStatement主要有如下的三個(gè)優(yōu)點(diǎn):

可以防止sql注入
由于使用了預(yù)編譯機(jī)制,執(zhí)行的效率要高于Statement
sql語(yǔ)句使用?形式替代參數(shù),然后再用方法設(shè)置?的值,比起拼接字符串,代碼更加優(yōu)雅.

PreparedStatement 與Statment比較:

語(yǔ)法不同:PreparedStatement可以使用預(yù)編譯的sql,而Statment只能使用靜態(tài)的sql
效率不同: PreparedStatement可以使用sql緩存區(qū),效率比Statment高
安全性不同: PreparedStatement可以有效防止sql注入,而Statment不能防止sql注入。

??必須使用Statement的情況

當(dāng)sql語(yǔ)句中必須用到字符串拼接時(shí),則必須使用Statement

public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        System.out.print("升序輸入asc,降序輸入desc:");
        String order = s.nextLine();
        // 定義變量
        Connection connection = null;
        Statement statement = null;
        ResultSet rs = null;
 
 
        try {
            // 注冊(cè)驅(qū)動(dòng)
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 獲取連接
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/MyTest","root", "********");
            // 獲取數(shù)據(jù)庫(kù)操作對(duì)象
            statement = connection.createStatement();
            // 執(zhí)行sql
            String sql = "select * from emp order by sal " + order;
            rs = statement.executeQuery(sql);
            // 處理查詢結(jié)果集
            while(rs.next()){
                String ename = rs.getString("ename");
                double sal = rs.getDouble("sal");
                System.out.println("姓名:" + ename + ",薪資:" + sal);
            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            // 釋放資源
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

到此這篇關(guān)于一文搞懂Java JDBC中的SQL注入問(wèn)題的文章就介紹到這了,更多相關(guān)jdbc sql 注入內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java常用對(duì)象操作工具代碼實(shí)例

    Java常用對(duì)象操作工具代碼實(shí)例

    這篇文章主要介紹了Java常用對(duì)象操作工具代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-12-12
  • Spring MVC整合FreeMarker的示例

    Spring MVC整合FreeMarker的示例

    這篇文章主要介紹了Spring MVC整合FreeMarker的示例,幫助大家更好的理解和使用Spring MVC,感興趣的朋友可以了解下
    2020-12-12
  • WebSocket 中使用 @Autowired 注入對(duì)應(yīng)為null的解決方案

    WebSocket 中使用 @Autowired 注入對(duì)應(yīng)為null的解決方案

    SpringBoot集成WebSocket時(shí),會(huì)遇到service對(duì)象為null的情況,原因是Spring默認(rèn)為單例模式與WebSocket的多對(duì)象模式相沖突,當(dāng)客戶端與服務(wù)器端建立連接時(shí),會(huì)創(chuàng)建新的WebSocket對(duì)象,本文給大家介紹WebSocket 中使用 @Autowired 注入對(duì)應(yīng)為null的問(wèn)題,感興趣的朋友一起看看吧
    2024-10-10
  • Springboot詳解線程池與多線程及阻塞隊(duì)列的應(yīng)用詳解

    Springboot詳解線程池與多線程及阻塞隊(duì)列的應(yīng)用詳解

    本例應(yīng)用線程池、多線程、阻塞隊(duì)列處理一個(gè)流程任務(wù)。本例處理一個(gè)訂單流程,主要包括生成訂單、訂單處理、訂單入庫(kù),下面我們一起看看
    2022-06-06
  • Java數(shù)據(jù)結(jié)構(gòu)之鏈表詳解

    Java數(shù)據(jù)結(jié)構(gòu)之鏈表詳解

    本篇文章我們將講解一種新型的數(shù)據(jù)結(jié)構(gòu)—鏈表,鏈表是一種使用廣泛的通用數(shù)據(jù)結(jié)構(gòu),它可以用來(lái)作為實(shí)現(xiàn)棧,隊(duì)列等數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ).文中有非常詳細(xì)的介紹,需要的朋友可以參考下
    2021-05-05
  • IDEA使用入門(mén)小白操作教程

    IDEA使用入門(mén)小白操作教程

    IntelliJ IDEA,就是Java語(yǔ)言開(kāi)發(fā)工具 (IDE) 功能與Eclipse同類!本文通過(guò)圖文并茂的形式給大家介紹IntelliJ IDEA使用入門(mén)教程,非常適合新手小白操作,感興趣的朋友一起看看吧
    2020-10-10
  • 五分鐘帶你了解Java的接口數(shù)據(jù)校驗(yàn)

    五分鐘帶你了解Java的接口數(shù)據(jù)校驗(yàn)

    這篇文章主要介紹了五分鐘帶你了解Java的接口數(shù)據(jù)校驗(yàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Java優(yōu)秀測(cè)試框架TestNG詳解

    Java優(yōu)秀測(cè)試框架TestNG詳解

    這篇文章主要為大家詳細(xì)介紹了Java優(yōu)秀測(cè)試框架TestNG,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02
  • Spring Boot中使用Actuator的/info端點(diǎn)輸出Git版本信息

    Spring Boot中使用Actuator的/info端點(diǎn)輸出Git版本信息

    這篇文章主要介紹了Spring Boot中使用Actuator的/info端點(diǎn)輸出Git版本信息,需要的朋友可以參考下
    2017-06-06
  • java得到某年某周的第一天實(shí)現(xiàn)思路及代碼

    java得到某年某周的第一天實(shí)現(xiàn)思路及代碼

    某年某周的第一天,此功能如何使用java編程得到呢?既然有了問(wèn)題就有解決方法,感興趣的朋友可以了解下本文,或許會(huì)給你帶來(lái)意想不到的收獲哦
    2013-01-01

最新評(píng)論