最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文搞懂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();
        //編寫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開始,為指定參數(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)閉流的方式一樣,先開的后關(guān),后開的先關(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 反轉(zhuǎn)帶頭結(jié)點(diǎn)的單鏈表并顯示輸出的實(shí)現(xiàn)過(guò)程

    Java 反轉(zhuǎn)帶頭結(jié)點(diǎn)的單鏈表并顯示輸出的實(shí)現(xiàn)過(guò)程

    這篇文章主要介紹了Java 反轉(zhuǎn)帶頭結(jié)點(diǎn)的單鏈表并顯示輸出,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-11-11
  • 一文帶你搞懂Java定時(shí)器Timer的使用

    一文帶你搞懂Java定時(shí)器Timer的使用

    定時(shí)器類似于我們生活中的鬧鐘,可以設(shè)定一個(gè)時(shí)間來(lái)提醒我們。而定時(shí)器是指定一個(gè)時(shí)間去執(zhí)行一個(gè)任務(wù),讓程序去代替人工準(zhǔn)時(shí)操作。本文就來(lái)聊聊Java定時(shí)器Timer的使用,需要的可以參考一下
    2023-01-01
  • Java基礎(chǔ)學(xué)習(xí)之ArrayList類概述與常用方法

    Java基礎(chǔ)學(xué)習(xí)之ArrayList類概述與常用方法

    這篇文章主要為大家簡(jiǎn)單的介紹Java中ArrayList類的概述、常用方法及存儲(chǔ)字符串并遍歷,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2022-08-08
  • 23種設(shè)計(jì)模式(8) java外觀模式

    23種設(shè)計(jì)模式(8) java外觀模式

    這篇文章主要為大家詳細(xì)介紹了23種設(shè)計(jì)模式之java外觀模式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Java?枚舉的常用技巧匯總

    Java?枚舉的常用技巧匯總

    在Java中,枚舉類型是一種特殊的數(shù)據(jù)類型,允許定義一組固定的常量,默認(rèn)情況下,toString方法返回枚舉常量的名稱,本文提供了一個(gè)完整的代碼示例,展示了如何在Java中通過(guò)重寫枚舉的toString方法來(lái)展示枚舉實(shí)例的字段信息,感興趣的朋友一起看看吧
    2025-01-01
  • JavaWeb案例講解Servlet常用對(duì)象

    JavaWeb案例講解Servlet常用對(duì)象

    Java Servlet 是運(yùn)行在 Web 服務(wù)器或應(yīng)用服務(wù)器上的程序,它是作為來(lái)自 Web 瀏覽器或其他 HTTP 客戶端的請(qǐng)求和 HTTP 服務(wù)器上的數(shù)據(jù)庫(kù)或應(yīng)用程序之間的中間層
    2021-10-10
  • java 深拷貝與淺拷貝機(jī)制詳解

    java 深拷貝與淺拷貝機(jī)制詳解

    這篇文章主要介紹了 java 深拷貝與淺拷貝機(jī)制詳解的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • MyBatis緩存功能原理及實(shí)例解析

    MyBatis緩存功能原理及實(shí)例解析

    這篇文章主要介紹了MyBatis緩存功能原理及實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • Java基于socket編程相關(guān)知識(shí)解析

    Java基于socket編程相關(guān)知識(shí)解析

    這篇文章主要為大家詳細(xì)解析了Java基于socket編程的相關(guān)知識(shí),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • SpringBoot異步調(diào)用方法實(shí)現(xiàn)場(chǎng)景代碼實(shí)例

    SpringBoot異步調(diào)用方法實(shí)現(xiàn)場(chǎng)景代碼實(shí)例

    這篇文章主要介紹了SpringBoot異步調(diào)用方法實(shí)現(xiàn)場(chǎng)景代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04

最新評(píng)論

遂平县| 瑞金市| 深水埗区| 密山市| 连州市| 兴宁市| 古交市| 鲜城| 南江县| 山丹县| 马山县| 花莲县| 焉耆| 威海市| 宿迁市| 永顺县| 柞水县| 太仆寺旗| 大田县| 那坡县| 华阴市| 高雄市| 新宁县| 中山市| 永春县| 古田县| 巧家县| 贵阳市| 温州市| 新乡县| 青田县| 农安县| 精河县| 罗山县| 万盛区| 天水市| 阿拉尔市| 望江县| 乌鲁木齐市| 怀安县| 吉林省|