MySQL之SQL注入及防止

SQL注入

  • 我们发现,按照上面的方法进行操作,无论密码是否正确,都提示我们登陆成功,这显然是不合理的。问题出在哪里呢?
  • 字符串拼接后的SQL语句是:
    select * from users where username = ‘kuangshen’ or 1 = 1 and password = ‘"+password+"’;
  • 运行到or的时候已经是条件成立,所以无论后面是否正确,无需验证密码即可登陆成功。
  • 上面的问题都是通过在SQL语句中添加特殊的字符,构成关键字,改变了程序运行轨迹,从而对数据进行操作。

SQL注入问题:是指通过客户输入到后台的那些能到数据库得到数据的位置上,恶性的输入一些对数据有害的操作。

PreparedStatement

PreparedStatement对象介绍

  • PreperedStatement是Statement的子类
  • 它的实例对象可以通过调Connection.preparedStatement()方法获得,相对于Statement对象而言:PreperedStatement可以避免SQL注入的问题。
  • Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement可对SQL进行预编译,从而提高数据库的执行效率。
  • 并且PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。

演示:

使用PreparedStatement对象完成对数据库的CRUD操作
案例:

package com.kuang.dao;

import com.kuang.utils.JDBCUtils;

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

//防止SQL注入
public class Demo03 {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);

        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            //1.获取数据库连接
            connection = JDBCUtils.getConnection();


            //prepareStatement解决sql注入问题
            //select * from users where id = 1
            //System.out.print("请输入你要查询的用户名:");
            //String username = scanner.nextLine();

            /*
            preparedStatement【推荐使用】 和 Statement;
            相同点 : 都是用来执行sql语句的
            不同点 :
                Statement 不安全 , 不能预编译SQL , 不能使用占位符 , 容易造成SQL语句拼接错误
                preparedStatement  安全 , 预编译SQL语句 , 可以使用 ? 占位符 ,SQL更清晰。

            如何给preparedStatement的占位符赋值
                preparedStatement.setXXX [xxx:对应占位符数据的类型] (?索引[从1开始] , 传入的值)

            Statement 先写SQL语句再执行; Statement.execute(SQL)
            preparedStatement 直接编译SQL , 调用方法执行 ;  preparedStatement.execute();

            */

            preparedStatement = connection.prepareStatement("select * from users where id = ? and name = ?");

            preparedStatement.setInt(1,4);
            preparedStatement.setString(2,"qinjiang");

            //preparedStatement.setString(1,username);

            resultSet = preparedStatement.executeQuery();

            while (resultSet.next()){
                System.out.println(resultSet.getString("name"));
                System.out.println(resultSet.getString("password"));
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //5.释放资源
            JDBCUtils.closeAll(resultSet,preparedStatement,connection);
        }

    }
}


事务

案例:

package com.kuang.dao;

import com.kuang.utils.JDBCUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Demo04 {
    /*
        事务 : 一组sql语句要么都成功,要么都失败;
        开启事务 setAutoCommit(false);
        提交事务 commit ;
        回滚事务 rollback ;

        #开启事务后 , 如果不提交事务 , 那么所有的操作在mysql连接断开后,会回复到最开始的样子;
        #开启事务后 , 更新了数据 , 不想更新了 , 可以选择回滚;
    */


    public static void main(String[] args) throws SQLException {

        Connection connection = JDBCUtils.getConnection();

        //start transaction
        connection.setAutoCommit(false);  //关闭数据库的事务自动提交 = 通知数据库开启事务控制;

        String sql = "update account set money = money - 100 where name='A'";

        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.execute();

        connection.rollback();
        //connection.commit(); //提交事务


        JDBCUtils.closeAll(null,preparedStatement,connection);


    }



}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值