SQL注入与Statement缺点

说明

SQL注入,一般用于 破解登录,即:不知道用户名、密码的情况下,进行登录

MySQL 注入原理

会被注入的 SQL,是将 用户名、密码 拼接 到 SQL中,如下:

String sql="select * from user where username='"+username+"' and password='"+password+"' ";

正常用户名、密码

当输入 正常 的用户名、密码,如:用户名:lilei,密码:123456,拼接结果如下:

select * from user where username='lilei' and password='123456'

是正确的

SQL注入

SQL注入的方式:用户名写 ' or 1=1 #,密码写不写都行,拼接结果如下:

select * from user where username='' or 1=1 #' and password=''

解释:

  • 用户名开始的 ',与 sql中的 ' 匹配
  • 最后的 # 号,在 mysql 数据库中,表示 注释
  • 由于有 or 1=1,那么一定能够查询出结果

代码演示

使用 JDBC的 Statement,就会发生 SQL注入

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class SQL注入 {

    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        String url = "jdbc:mysql://127.0.0.1:3308/scott?useSSL=false";

//        正常的用户名、密码
//        String username = "lilei";
//        String password = "123456";

        // sql注入
        String username = "' or 1=1 #";
        String password = "";


        // 加载驱动
        Class.forName("com.mysql.jdbc.Driver");

        Connection conn = DriverManager.getConnection(url, "root", "");

        Statement stmt = conn.createStatement();

        String sql = "SELECT * FROM USER WHERE username='" + username + "' and password='"+ password + "'";
        System.out.println(sql);

        ResultSet rs = stmt.executeQuery(sql);

        if (rs.next()) {
            String id = rs.getString(1);
            Object name = rs.getObject(2);
            Object passowrd = rs.getObject(3);

            System.out.println("登录成功!");
            System.out.println(id + "," + name + "," + passowrd);
        } else {// 没有查询到此用户、密码,说明登录失败
            System.out.println("输入用户名或密码错误,请重新输入!");
        }

        conn.close();
    }

}

解决

采用 JDBC PreparedStatement 占位符 的方式,可以很好的避免 SQL注入 的问题


原文出处:http://malaoshi.top/show_1IX2aMXBCjLn.html