SQL注入问题以及解决方法

sql注入

       SQL Injection:就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。

-- 代码中的SQL语句

   "SELECT * FROM user WHERE name='" + name + "' AND password='" + password + "';";

-- 将用户输入的账号aaa和密码:a' or '1'='1拼接后

    "SELECT * FROM user WHERE name='aaa' AND password='a' or '1'='1';"

我们让用户输入的密码和SQL语句进行字符串拼接。用户输入的内容作为了SQL语句语法的一部分,改变了原有SQL真正的意义,以上问题称为SQL注入。 要解决SQL注入就不能让用户输入的密码和我们的SQL语句进行简单的字符串拼接。

 

防止sql注入的解决方法:PreparedSatement预编译对象

(1)PreparedSatement的执行原理

我们写的SQL语句让数据库执行,数据库不是直接执行SQL语句字符串。和Java一样,数据库需要执行编译后的SQL语句(类似Java编译后的字节码文件)。

1.statement对象每执行一条SQL语句都会先将这条SQL语句发送给数据库编译,数据库再执行

Statement stmt = conn.createStatement();
stmt.executeUpdate("INSERT INTO users VALUES (1, '张三', '123456');");
stmt.executeUpdate("INSERT INTO users VALUES (2, '李四', '666666');");

上面2条SQL语句我们可以看到大部分内容是相同的,只是数据略有不一样。数据库每次执行都编译一次。如果有1万条类似的SQL语句,数据库需要编译1万次,执行1万次,显然效率就低了。

public class JdbcPrecompile {
    public static void main(String[] args) {
        Connection conn =null;
        PreparedStatement preparedStatement =null;
        try {
            conn = JdbcUtilDemo02.getConnection();
            String sql="insert into user(name,username,password) values (?,?,?)";
            //预编译sql语句
            preparedStatement = conn.prepareStatement(sql);

            //设置sql语句中的参数
            preparedStatement.setString(1,"张三");
            preparedStatement.setString(2,"spsglz");
            preparedStatement.setString(3,"123456");
            preparedStatement.executeUpdate();
            
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
           //关流
        }
    }
}

prepareStatement()会先将SQL语句发送给数据库预编译。PreparedStatement会引用着预编译后的结果。可以多次传入不同的参数给PreparedStatement对象并执行。相当于调用方法多次传入不同的参数。

(2)PreparedSatement的好处

1.prepareStatement()先将SQL语句发送给数据库预编译。PreparedStatement会引用着预编译后的结果。可以多次传入不同的参数给PreparedStatement对象并执行。减少SQL编译次数,提高效率。

2.安全性更高,没有SQL注入的隐患。

3.提高了程序的可读性

(3)PreparedSatement的基本使用

PreparedStatement prepareStatement(String sql)  
//会先将SQL语句发送给数据库预编译。PreparedStatement对象会引用着预编译后的结果。
void setDouble(int parameterIndex, double x) 
//将指定参数设置为给定 Java double 值。
void setFloat(int parameterIndex, float x) 
//将指定参数设置为给定 Java REAL 值。
void setInt(int parameterIndex, int x) 
//将指定参数设置为给定 Java int 值。
void setLong(int parameterIndex, long x) 
//将指定参数设置为给定 Java long 值。
void setObject(int parameterIndex, Object x) 
//使用给定对象设置指定参数的值。  
void setString(int parameterIndex, String x) 
//将指定参数设置为给定 Java String 值。 
ResultSet executeQuery() 
//在此 PreparedStatement 对象中执行 SQL 查询,并返回该查询生成的ResultSet对象。 
int executeUpdate() 
//在此 PreparedStatement 对象中执行 SQL 语句,该语句必须是一个 SQL 数据操作语言DML语句
//比如 INSERT、UPDATE 或 DELETE 语句;或者是无返回内容的 SQL 语句,比如 DDL 语句。 

(4)PreparedSatement使用步骤

    1. 编写SQL语句,未知内容使用?占位:"SELECT * FROM user WHERE name=? AND password=?;";
    2. 获得PreparedStatement对象
    3. 设置实际参数
    4. 执行参数化SQL语句
    5. 关闭资源
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值