编译预处理机制(SQL注入问题解决原理)

预编译

首先,什么时编译预处理机制? 字面理解就是预先进行编译
那么,预编译处理机制有什么用? 可以解决SQL注入问题
那么,问题又来了,什么是sql注入呢? 简单来说就是应用程序没有对用户输入数据进行校验或者过滤不严格

内容讲解及代码展示

了解什么时预编译和sql注入,在这里我用jdbc实现用户登录原理来给大家讲解预编译和sql注入
大家可以预先了解
jdbc上手(上)
jdbc上手(下)
首先,先回顾一下jdbc步骤

  1. 加载连接数据库驱动
  2. 与数据库建立连接
  3. 生成与数据库对话的对象
  4. 与数据库进行对话
  5. 收尾

然后,看一下没有预编译的效果

原理:通过jdbc与数据库建立连接,当我们输入用户名及密码时,在数据库进行校验,如果数据库有这条记录即为登录成功,否则为登录失败
数据库表
在这里插入图片描述

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

public class jdbctest {
    public static void main(String[] args) throws SQLException {
        Scanner scanner=new Scanner(System.in);
        //1加载驱动
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            System.err.println("驱动加载失败!!!");
            e.printStackTrace();
        }
        //2建立与数据库连接
        Connection conn=null;
        try {
            conn= DriverManager.getConnection("jdbc:mysql://localhost:33060/mytest","root","Root");
        } catch (SQLException e) {
            System.err.println("数据库连接建立失败!!!");
            e.printStackTrace();
        }
        //3根据连接生成与数据库对话的对象
        Statement stmt=null;
        try {
            stmt=conn.createStatement();
        } catch (SQLException e) {
            System.err.println("生成与数据库对话的对象失败!!!");
            e.printStackTrace();
        }

        //4与数据库进行对话
        ResultSet res=null;
        while(true){
            System.out.println("请输入用户名和密码!!");
            String username=scanner.next();
            String userpwd =scanner.next();
            String execuetquery=" select * from users where nuername='"+username+"' and userpwd='"+ userpwd +"' ";


                res=stmt.executeQuery(execuetquery);


                if (res.next()){
                    System.out.println("登录成功!!");
                    System.out.println("您的账户为:"+res.getObject("nuername")+"您的密码为:"+res.getObject("userpwd"));
                    break;
                }else{
                    System.out.println("登录失败!!");
                }


        }


        //5收尾
        if (res!=null){
                res.close();
        }
        if (stmt!=null) {
                stmt.close();
        }
        if (conn!=null) {
                conn.close();
        }
    }
}

在这里插入图片描述
在我们的数据库中只有两条记录,所以正常情况下只有用户名和密码与这两条记录中的一条符合时才会显示登录成功,但是,这个是后就会出现sql注入问题,大家看下面的截图!
在这里插入图片描述
我随便输入了一个用户名,输入的密码在数据库中也没有记录,但是却登录成功,这样就出现了sql注入漏洞
下面,我为大家详细解释sql注入漏洞

利用SQL语句的字符串拼接过程将(OR 永真条件)强行注入到原查询SQL中,导至原有查询条件全部失效
的处理手法。
例如:String querySQL = "SELECT * FROM Users WHERE username='"+userName+"' AND
userpwd='"+userPwd+"'";
正常应输入正确的用户名和密码即可组合成正确的查询语句,效果如下:SELECT * FROM Users
WHERE usernane='admin' AND userPwd='admin';
如发生SQL注入漏洞处理,则输入的信息可能为('OR'1'='1),
最终注入效果如下:SELECT * FROM Users WHERE usernane='errorname' AND
userPwd='errorpwd'OR'1'='1';

下面给大家展示具有预编译处理的代码(只是在第3-5步与上面的代码有差异):

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

public class jdbctest2 {
    public static void main(String[] args) throws SQLException {
        Scanner scanner=new Scanner(System.in);
        //1加载驱动
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            System.err.println("驱动加载失败!!!");
            e.printStackTrace();
        }
        //2建立与数据库连接
        Connection conn=null;
        try {
            conn= DriverManager.getConnection("jdbc:mysql://localhost:33060/mytest","root","Root");
        } catch (SQLException e) {
            System.err.println("数据库连接建立失败!!!");
            e.printStackTrace();
        }

        //3根据连接生成与数据库对话的支持预编译处理的对象
        String Query="select * from users where nuername=? and userpwd=?"; //用?代替要填入的内容
        PreparedStatement pstmt=null;
        pstmt=conn.prepareStatement(Query);
        pstmt.setObject(1,"");

        //4与数据库进行对话
        ResultSet res=null;
        while(true){
            System.out.println("请输入用户名和密码!!");
            String username=scanner.next();
            String userpwd =scanner.next();

            pstmt.setObject(1,username);
            pstmt.setObject(2,userpwd);


            res=pstmt.executeQuery();


            if (res.next()){
                System.out.println("登录成功!!");
                System.out.println("您的账户为:"+res.getObject("nuername")+"您的密码为:"+res.getObject("userpwd"));
                break;
            }else{
                System.out.println("登录失败!!");
            }


        }


        //5收尾
        if (res!=null){
            res.close();
        }
        if (pstmt!=null) {
            pstmt.close();
        }
        if (conn!=null) {
            conn.close();
        }
    }
}

在生成对象时,生成的是支持预编译的对象,用?代替内容进行预编译,然后用户输入的信息就不会参与到之前的sql语句中。这样就起到了预编译预防sql注入的作用!!

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我的大男子主义

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值