1. 程式人生 > 資料庫 >解決 SQL 注入

解決 SQL 注入

SQL注入是什麼?

看一下百度百科的定義:

在這裡插入圖片描述
啊,好長一大段文字,些許不想看,下面通過一個例子,來說明一下什麼是SQL注入

新建一個數據庫,再建一個表,新增兩行資料:

use db1;
create table user(
	id int primary key auto_increment,
	username varchar(32),
	password varchar(32)
);

insert into user values(null,'zhangsan','123');
insert into user values(null,'lisi','234');

表如下圖所示:

在這裡插入圖片描述
再隨隨便便用JDBC寫個登陸操作:

package com.wzq.jdbc;

import com.wzq.util.JDBCUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
/*
 *   需求:
 *       1、通過鍵盤錄入使用者名稱和密碼
 *       2、判斷使用者是否登陸成功
 * */
public class JDBCDemo05 {

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        System.out.println("請輸入使用者名稱:");
        String username = cin.nextLine();
        System.out.println("請輸入密碼:");
        String password = cin.nextLine();

        boolean res = new JDBCDemo05().login(username, password);
        if (res) System.out.println("登陸成功!");
        else System.out.println("登陸失敗!");

    }

    public boolean login(String username, String password) {
        if (username == null || password == null) {
            return false;
        }
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            //1、獲取資料庫連線
            conn = JDBCUtils.getConnection();   //JDBCUtils工具類
            //2、定義sql
            String sql = "select * from user where username = '" + username + "' and password = '" + password + "'";
            //3、獲取執行sql的物件
            stmt = conn.createStatement();
            //4、執行sql
            rs = stmt.executeQuery(sql);
            return rs.next();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(rs, stmt, conn);
        }
        return false;
    }
}

測試一下:
在這裡插入圖片描述
可以看到,普通的檢驗沒有任何問題,現在使用SQL注入

賬戶名稱隨便輸入,密碼輸入:a' or 'a'='a
在這裡插入圖片描述
驚訝的發現,居然登陸成功了。輸出一下sql看一下:

select * from user where username = 'askjdhjksahd' and password = 'a' or 'a' = 'a'

可以看到where之後的條件,無論是什麼結果都為真,都會輸出整個表:
在這裡插入圖片描述
所以,綜上所述:在sql拼接時,有一些sql的特殊關鍵字參與字串的拼接,就會造成安全性問題,這就是上面為什麼能登陸成功的原因所在。


那怎麼解決這個問題呢?

答:利用PreparedStatement

物件,不使用Statement物件。

PreparedStatement物件是Statement物件的子類,它是預編譯的sql,所以執行速度會比Statemnet更快。

PerpaerdStatement使用?作為佔位符,使用setXxx(索引,值)?賦值

所以我們替換一下Statement,寫一下程式碼:

    public boolean login(String username, String password) {
        if (username == null || password == null) {
            return false;
        }
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            //1、獲取資料庫連線
            conn = JDBCUtils.getConnection();   //JDBCUtils類
            //2、定義sql
            String sql = "select * from user where username = ? and password = ?";
            //3、獲取執行sql的物件
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1,username);
            pstmt.setString(2,password);
            //4、執行sql
            rs = pstmt.executeQuery();
            return rs.next();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(rs, pstmt, conn);
        }
        return false;
    }

測試一下:
在這裡插入圖片描述
成功解決!