详解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
  • 条件 A :username='1111'
  • 条件 B :password='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();
    }
}
相关推荐
余槐i7 小时前
200万行表加索引锁死写入:PostgreSQL CONCURRENTLY 的三类等待与重建路径
数据库·postgresql·性能优化·索引·explain
物联网软硬件开发-轨物科技7 小时前
【轨物洞见】什么是产品碳足迹(PCF)?ISO 14067 计算方法与应用场景深度解读
大数据·网络·人工智能
北龙云海8 小时前
AI驱动数据库运维变革:北龙云海智能巡检平台实践与展望
运维·数据库·人工智能
带金箍的至尊宝8 小时前
系统架构设计师笔记 05:第2章硬件与软件基础,冯诺依曼结构怎么考
数据库·笔记·系统架构
蟕初的梦想8 小时前
Claude Haiku 5.5 效能实测与场景应用指南
数据库·人工智能·大模型
专注API从业者8 小时前
告别复杂页面解析,OpenClaw 快速搭建电商商品监控与数据分析脚本
大数据·数据库·python·数据挖掘·数据分析
naturliche9 小时前
sgx支持数据库环境配置,编译,debug
数据库·编译·sgx
SelectDB9 小时前
Apache Doris x Fluss:面向湖流一体的统一查询与分析
大数据·数据库·数据分析
云贝贝贝9 小时前
Oracle 备份恢复实战:RMAN 备份、恢复与误删闪回
数据库
java1234_小锋9 小时前
【技术专题】Mysql8 数据库 - Mysql8 触发器
数据库·mysql·mysql8