详解SQL注入问题

一、代码漏洞根源

核心危险代码:

复制代码
// 直接拼接用户输入拼接SQL语句
String sql="select * from password where username='"+username+"'and password='"+password+"'";

使用 Statement + 字符串拼接 SQL ,用户输入的内容会直接拼入 SQL 语句,数据库会执行输入里的 SQL 逻辑,造成注入攻击。

二、注入攻击演示

1. 恶意输入

  • 用户名输入:

    1111

  • 密码输入:

    1' or '1' ='1

2. 拼接后最终执行 SQL,恒成立

复制代码
select * from password where username='1111'and password='1' or '1' ='1'

输出:

三、SQL 能登录成功的核心逻辑

数据库是这样计算的:

复制代码
where (条件A  and  条件B)  or  条件C
  • 条件 Ausername='1111'
  • 条件 Bpassword='1'
  • 条件 C'1'='1'永远成立!

最终结果:

复制代码
假 and 假  or  真
= 假 or 真
= 真

只要有一个条件成立,整个 WHERE 就成立!直接查到数据 → 登录成功!

本来想让数据库验证:

复制代码
用户名正确 并且 密码正确

结果被用户改成了:

复制代码
(用户名正确 并且 密码正确) 或者 1=1

1=1 永远是对的,所以不管用户名密码是什么,都能登录!


五、SQL 注入原理

用户输入的内容里带 SQL 语法,直接破坏了原本的查询逻辑,可以实现绕过密码登录。

  1. 前端用户输入带有 SQL 语法的特殊字符
  2. 后端无过滤,直接把输入拼入完整 SQL
  3. MySQL 识别拼接后的完整 SQL 并执行恶意逻辑
  4. 实现越权查询、篡改、删除数据

六、高危注入危害输入

  • 篡改全部数据
  • 直接删除数据表

七、解决方案(杜绝 SQL 注入)

  1. 放弃 Statement,使用 PreparedStatement 预编译对象
  2. 使用 ? 作为占位符替代字符串拼接
  3. 预编译会把用户输入全部当成普通文本,不会解析执行 SQL 语法

安全修复代码

复制代码
package com.qcby.sql;

import java.sql.*;
import java.util.Scanner;

public class LoginUtil {
    public static void main(String[] args) throws Exception{
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入用户名");
        String username=scanner.nextLine();
        System.out.println("请输入密码");
        String password=scanner.nextLine();
        safeLogin(username,password);
    }

    public static void safeLogin(String username,String pwd) throws Exception{
        Class.forName("com.mysql.cj.jdbc.Driver");
        String url="你的数据库";
        String user="***";
        String password="****";
        Connection connection= DriverManager.getConnection(url,user,password);

        // 使用占位符,禁止字符串拼接
        String sql = "select * from password where username=? and password=?";
        PreparedStatement pstmt = connection.prepareStatement(sql);
        // 给占位符赋值
        pstmt.setString(1,username);
        pstmt.setString(2,pwd);

        ResultSet set=pstmt.executeQuery();
        if(set.next()){
            System.out.println("登录成功");
        }else{
            System.out.println("登录失败");
        }
        set.close();
        pstmt.close();
        connection.close();
    }
}
相关推荐
唐青枫9 小时前
MySQL JSON 实战详解:从存储、查询、更新到 JSON_TABLE 与索引
sql·mysql
吃糖的小孩9 小时前
给 QQ AI 机器人设计“可控记忆”:会话摘要、手动长期记忆与角色卡边界
数据库
笃行3501 天前
金仓数据库数据安全双防线:静态存储加密与传输加密实战
数据库
笃行3501 天前
金仓数据库物理备份实战:sys_rman 全流程演练与误覆盖抢救
数据库
笃行3501 天前
金仓数据库逻辑备份实战:从全库导出到 Schema 替换的完整闭环
数据库
SelectDB2 天前
阶跃星辰基于 SelectDB 构建 PB 级 Agent 可观测平台
大数据·数据库·aigc
这个DBA有点耶2 天前
GROUP BY优化全解:如何写出既不丢数据又飞快的分组查询
数据库·mysql·架构
掉头发的王富贵2 天前
【StarRocks】极限十分钟入门StarRocks
数据库·sql·mysql
Nturmoils2 天前
WHERE 条件别凭习惯写,常用查询先跑一遍
数据库