SQL学习五——SQL注入相关

文章目录

    • UNION
    • 关于$和#
        • 区别
        • $方式传入表名
        • 防止SQL注入的方法
    • PreparedStatement
        • PreparedStatement是什么
        • PreparedStatement的优势
        • PreparedStatement防止SQL注入
        • 局限性

这里补充一些模糊的概念
看SQL注入部分涉及到了UNION等,简单的总结一下

UNION

简单的说 UNION就是对于结构相同的结果做集合的感觉

  • UNION 操作符用于合并两个或多个 SELECT 语句的结果集。

  • 请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。

SELECT column_name(s) FROM table_name1
UNION
SELECT column_name(s) FROM table_name2
  • 默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL
    https://www.w3school.com.cn/sql/sql_union.asp

关于$和#

https://www.cnblogs.com/luohanguo/p/9122398.html
结论:#很大程度可以防止SQL注入,$无法防止SQL注入

区别

  • #会将传入数据当作字符串,对传入数据自动加双引号,如:order by #user_id#,如果传入的值是id,则解析成的sql为order by "id"
  • $将传入的数据直接显示生成在sql中。如:order by $user_id$,如果传入的值是id,则解析成的sql为order by id
  • $方式一般用于传入数据库对象,例如传入表名。(这里得注意SQL注入问题)
  • $方式一般用于传入数据库对象,例如传入表名。(这里得注意SQL注入问题)

$方式传入表名

$方式一般用于传入数据库对象,例如传入表名。(这里得注意SQL注入问题)

  • 举例子:select * from ${table_Name} where name = #{name} ;
  • 在这个例子中,如果表名为user; delete user; --,则动态解析之后 sql 如下:select * from user; delete user; -- where name = ?;
  • --之后的语句被注释掉,而原本查询用户的语句变成了查询所有用户信息+删除用户表的语句,会对数据库造成致命损伤。
  • 但是表名用参数传递进来的时候,只能使用 ${} 。这也提醒在这种用法中要小心sql注入的问题。

防止SQL注入的方法

防止SQL注入方法:

首先,永远不要相信用户的输入。

  • 不使用SQL,考虑NoSQL。

  • 正则表达式,字符串过滤。

  • 参数绑定PreparedStatement。

  • 使用正则表达式过滤传入的参数。

  • JSP中调用该函数检查是否包函非法字符或JSP页面判断代码。JSP参考JSP使用过滤器防止SQL注入

PreparedStatement

参考Preparedstatement处理机制

PreparedStatement是什么

PreparedStatement是java.sql包下面的一个接口,用来执行SQL语句查询,通过调用connection.preparedStatement(sql)方法可以获得PreparedStatment对象。数据库系统会对sql语句进行预编译处理(如果JDBC驱动支持的话),预处理语句将被预先编译好,这条预编译的sql查询语句能在将来的查询中重用,这样一来,它比Statement对象生成的查询速度更快。

PreparedStatement的优势

可以写动态参数化查询:SELECT interest_rate FROM loan WHERE loan_type=? 利用占位符动态赋值查询参数

  • 比Statement更快
  • 可以防止SQL注入

PreparedStatement防止SQL注入

在使用参数化查询的情况下,数据库系统(eg:MySQL)不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,因此就算参数中含有破坏性的指令,也不会被数据库所运行。 数据库只会执行我模板化的SQL语句,并提前在数据库中编译好,而不会执行参数中带有破坏性的指令

  • 在组合SQL字符串的时候,先对所传入的参数做字符取代(将单引号字符取代为连续2个单引号字符,因为连续2个单引号字符在SQL数据库中会视为字符中的一个单引号字符,
  • 譬如:strSQL = "SELECT * FROM users WHERE name = ' " + userName + " ';"
  • 传入字符串:userName = " 1' OR 1=1 "
  • 不做字符替换的话:strSQL = "SELECT * FROM users WHERE name ='1' OR 1=1'
  • 而替换的话:把userName做字符替换后变成:userName = " 1'' OR 1=1";最后生成的SQL查询语句为:strSQL = "SELECT * FROM users WHERE name = '1'' OR 1=1'
  • 这样数据库就会去系统查找name为“1′ ‘ OR 1=1”的记录,而避免了SQL注入。

局限性

为了防止SQL注入攻击,PreparedStatement不允许一个占位符(?)有多个值,在执行有IN子句查询的时候这个问题变得棘手起来。

你可能感兴趣的:(sql语言与数据库,sql)