JDBC之sql注入

目录

  • 一、上面是SQL注入
  • 二、SQL漏洞演示
  • 三、JDBC如何避免sql注入
    • 3.1PreparedStatement的介绍
    • 3.2优化后代码

一、上面是SQL注入

SQL注入是一种Web安全漏洞,就是传入的数据被当作SQL语句的一部分执行。事实上这种漏洞基本被规避了。

二、SQL漏洞演示

  1. 数据表
    JDBC之sql注入_第1张图片
  2. 代码
    代码做了一个根据姓名和密码查询用户的功能,如果可以查到则表示用户姓名密码存在,如果查到的为空,则表示账户名或密码错误。
public User findByNameAndPwd(String loginname,String password) {
       User user = new User();
       Connection con = null;
       Statement stat = null;
       ResultSet rs = null;
       try{

           con = JDBCUtils.getConnection();

           //3.获取执行者对象
           stat = con.createStatement();

           //4.执行sql语句,并且接收返回的结果集
           String sql = "SELECT * FROM user WHERE loginname='"+loginname+"'"+" and password='"+password+"'";
           System.out.println(sql);
           rs = stat.executeQuery(sql);

           //5.处理结果集
           while(rs.next()) {
               String uid = rs.getString("uid");
               String name = rs.getString("loginname");
               String passwd = rs.getString("password");

               //封装Student对象
               user.setUid(uid);
               user.setLoginname(name);
               user.setPassword(passwd);
           }

       } catch(Exception e) {
           e.printStackTrace();
       } finally {
           //6.释放资源
           JDBCUtils.close(con,stat,rs);
       }
       //将对象返回
       return user;
   }
  1. sql注入演示
@Test
    public void findByNameAndPwd() {
        User user = dao.findByNameAndPwd("zhangsan","222' or '1'='1");
        System.out.println(user);
    }

因为张三的密码是1234,按理来说这个222’ or ‘1’=‘1是不正确的,
dao.findByNameAndPwd(“zhangsan”,"222’ or ‘1’='1")。但是最后执行的sql是:SELECT * FROM user WHERE loginname=‘zhangsan’ and password=‘222’ or 1=‘1’,这就是传入的数据被当作SQL语句的一部分执行。

三、JDBC如何避免sql注入

3.1PreparedStatement的介绍

使用PreparedStatement的参数化的查询可以阻止大部分的SQL注入。在使用参数化查询的情况下,数据库不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,因此就算参数中含有破坏性的指令,也不会被数据库所运行。

3.2优化后代码

 public User findByLoginNameAndPassword(String loginname,String password) {
        User user = new User();
        Connection con = null;
        PreparedStatement pstm = null;
        ResultSet rs = null;
        try{

            //1.获取连接
            con = JDBCUtils.getConnection();
            //2.创建操作SQL对象
            String sql = "SELECT * FROM user WHERE loginname=? AND password=?";
            pstm = con.prepareStatement(sql);
            //3.设置参数
            pstm.setString(1,loginname);
            pstm.setString(2,password);
            System.out.println(pstm);
            //4.执行sql语句,获取结果集
            rs = pstm.executeQuery();

            //5.处理结果集
            while(rs.next()) {
                String uid = rs.getString("uid");
                String name = rs.getString("loginname");
                String passwd = rs.getString("password");

                //封装Student对象
                user.setUid(uid);
                user.setLoginname(name);
                user.setPassword(passwd);
            }

        } catch(Exception e) {
            e.printStackTrace();
        } finally {
            //6.释放资源
            JDBCUtils.close(con,pstm,rs);
        }
        //将对象返回
        return user;
    }
    ```
## 3.1小结
PreparedStatement的原理我不是很清楚,但是通过打印发现最后的执行语句为:
SELECT * FROM user WHERE loginname='zhangsan' AND password='222\' or \'1\'=\'1',把用户非法输入的单引号进行转义,最终传入参数作为一个整体执行,从而防止 SQL 注入。

你可能感兴趣的:(Java,sql,数据库,java)