SQL的注入问题

本文主要探讨数据库注入问题,以登录函数为例,展示了通过篡改输入数据实现SQL注入的方法,如利用or进行恒等判断套取数据库数据。为解决该问题,介绍了PreparedStatement对象,它可避免SQL注入且效率更高,还阐述了其防注入的本质是对传递参数进行字符处理和转义。

今天我们来谈个数据库注入问题

具体体现

注入定义在上面的传送门里了,我就不多嘴了
就以我上一篇最后的代码为例
其实是及其不安全的,很容易被注入
怎么实现呢?
篡改输入数据

正常的数据库交互肯定是要用户进行输入,数据库获得指令,并进行输出
比如以下登录函数(其内部登录SQL函数我就不具体写了)

public static void login(String name,String password){
        Connection conn = null;
        Statement st = null;
        ResultSet re = null;

        try {
            conn = JdbcUtils.getConnection();
            st = conn.createStatement();
            //SELECT * FROM users WHERE `NAME` = 'makerjack' AND `password` = '123456'
            String sql = "SELECT * FROM users WHERE `NAME` = '"+name+"' AND `password` = '"+password+"'";
            re = st.executeQuery(sql);

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(conn,st,re);
        }
    }

对应SQL应该是这样的
在这里插入图片描述
正常的登录(用户输入)及结果应该如下
在这里插入图片描述
但如果我们用这个语句呢

login(" ' or '1=1"," ' or '2=2");

数据全出来了!在这里插入图片描述
“他说他是乱打的……”
“他可不是乱打的嗷”

不够直观?

放到MySQL里面就是

SELECT * FROM users WHERE `NAME` = ' ' OR '1=1' AND `password` = ' ' OR '2=2'

直接利用or进行恒等判断,使得判定语句恒成立

如此直接套取了数据库的数据,实现SQL注入

如此一想,这很容易被攻击注入呀,该怎么办呢?

使用
PreparedStatement对象
其可以避免SQL注入且效率更高!

PreparedStatement对象

PreparedStatement对象可以防止SQL注入。效率也更高(以下简称PS)

在这里插入图片描述

其是继承Statement类,所以基本操作与Statement近似,创建变量也是如此

PreparedStatement st = null;

只是在赋值的时候,其操作需要预编译SQL

 String sql = "INSERT INTO users(`id`,`NAME`,`PASSWORD`,`email`,`birthday`) VALUES(?,?,?,?,?)";
//使用?作为占位符
st = conn.prepareStatement(sql);//预编译sql,先写SQL,不执行

在这之后进行具体字段赋值

st.setInt(1,5);
st.setString(2,"jack");
st.setString(3,"123456");
st.setString(4,"123456@qq.com");
//注意: java.sql.Date()  库是sql   需要导入java.sql.Date
//      java.Date()      库是util  需要导入java.util.Date
st.setDate(5,new java.sql.Date(new Date().getTime()));

增加数据如此,删 改 查 亦然。

那么当初那个登录的函数应该如下:

public static void login(String name,String password){
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet re = null;

        try {
            conn = JdbcUtils.getConnection();

            String sql = "SELECT * FROM users WHERE NAME = ? AND PASSWORD = ?";
            st = conn.prepareStatement(sql);
            st.setString(1,name);
            st.setString(2,password);
            re = st.executeQuery();
            while (re.next()){
                System.out.println("id="+re.getObject("id"));
                System.out.println("name="+re.getObject("NAME"));
                System.out.println("pwd="+re.getObject("PASSWORD"));
                System.out.println("email="+re.getObject("email"));
                System.out.println("birth="+re.getObject("birthday"));
                System.out.println("=====================================");
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(conn,st,re);
        }
}

主函数中调用登录函数(第一个是正常,第二个是注入)

public static void main(String[] args) {
        login("maker","123456");
        login(" ' ' or 1=1","123456");
}

在这里插入图片描述
测试结果如上图,第二个注入式登录没有任何结果返回
也没有报错

PreparedStatement防注入本质

其在setObjective() – 包括int String
时会把传递进来的参数当做字符处理
针对类似单引号 ’ 的转义字符,会直接转义处理掉
所以无法实施条件语句篡改

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值