写点什么

【MyBatis 1】SQL 注入,Java 技术功底不够如何去面试

用户头像
极客good
关注
发布于: 刚刚

五、预编译


=====


(一)预编译是什么



1、执行 sql 一般分为三步:

  • 语法和语义解析

  • 优化 sql 语句,制定执行计划

  • 执行 sql,返回结果

2、PreparedStatement

很多情况下,我们的一条 sql 语句可能被反复执行,或每次执行的时候只有个别的值不同,比如 query 的 where 子句值不同,update 的 set 子句值不同,insert 的 value 值不同。


如果每次都需要经过上面的语法语义解析、语句优化、制定执行计划等操作,效率显而易见,很低。


所谓预编译就是将这些语句中的值用占位符替代,可以视为将 sql 语句模板化或者参数化,一般称这类语句叫 PreparedStatement。


预编译语句的优势在于:一次编译、多次执行,省去了解析优化等繁琐过程,此外预编译语句能防止 sql 注入。


(二)预编译的 sql 语句处理




预编译语句 PreparedStatement 是 java.sql 中的一个接口,它是 Statement 的子接口。通过 Statement 对象执行 sql 语句时,需要将 sql 语句发送给 DBMS,由 DBMS 首先进行编译后再执行。预编译语句和 Statement 不同,在创建 PreparedStatement 对象时就指定了 sql 语句,该语句立即发送给 DBMS 进行编译。当该编译语句被执行时,DBMS 直接运行编译后的 sql 语句,而不需要像其它 sql 语句那样首先将其编译。预编译的 sql 语句处理性能稍微高于普通的传递变量的方法。


数据库管理系统(Database Management System)是一种操纵和管理数据库的大型软件,用于建立、使用和维护数据库,简称 DBMS。它对数据库进行统一的管理和控制,以保证数据库的安全性和完整性。用户通过 DBMS 访问数据库中的数据,数据库管理员也通过 DBMS 进行数据库的维护工作。它可以支持多个应用程序和用户去建立,修改和访问数据库。大部分 DBMS 提供数据定义语言 DDL 和数据操作语言 DML,供用户定义数据库的模式结构与权限约束,实现对数据的追加、删除等操作。


(三)预编译语句的作用



1、提高效率

当需要对数据库进行数据插入、更新或删除的时候,程序会发送整个 sql 语句给数据库处理和执行。数据库处理一个 sql 语句,需要完成解析 sql 语句、检查语法和语义以及生产代码,处理时间要比执行语句所需要的时间长。预编译语句在创建的时候就已经是将指定的 sql 语句发送给了 DBMS,完成了解析、检查、编译等工作。因此,当一个 sql 语句需要执行多次时,使用预编译语句可以减少处理时间,提高执行效率。

2、提高安全性

例如上面的 sql 注入攻击实例,登录验证,根本不用,直接进,加入又在后面追加上 drop table student;我靠,防不胜防,数据表直接没了,很多数据库是不会成功的,但也有很多数据库可以使用这些语句执行,而如果使用预编译语句,传入的任何内容就不会和原来的语句发生任何匹配的关系。只要全使用预编译语句,就用不着对传入的数据做任何过虑,而如果使用普通的 statement,有可能要对 drop,等做费尽心机的判断和过虑。


(四)预编译语句的使用



1、创建 PreparedSt

【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


atement 对象


String sql = "insert into studentvalues(?,?,?,?)";//组织一条含有参数的 SQL 语句


PreparedStatement ps = conn.prepareStatement(sql);


insert into student values(?,?,?,?);//它已发送给 DBMS,并为执行作好了准备。

2、传递 IN 参数

在执行 PreparedStatement 对象之前,必须设置每个 ? 参数的值。这可通过调用 setXXX 方法来完成,其中 XXX 是与该参数相应的类型。


(五)为什么 PreparedStatement 可以防止 sql 注入




Preparement 样式为


select * from student where id=? and name=?


该 SQL 语句会在得到用户的输入之前先用数据库进行预编译,这样的话不管用户输入什么 id 和用户名的判断始终都是并的逻辑关系,防止了 SQL 注入。


简单总结,参数化能防注入的原因在于,语句是语句,参数是参数,参数的值并不是语句的一部分,数据库只按语句的语义跑,至于跑的时候是带一个普通背包还是一个怪物,不会影响行进路线,无非跑的快点与慢点的区别。



===================================================================================================================================================================================================


六、mybatis 与 sql 注入


===============


<?xml version="1.0" encoding="UTF-8" ?>


<!DOCTYPE mapper


PUBLIC "-//mybatis.org//DTD Config 3.0//EN"


"http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="com.guor.mapper.StudentMapper">


<select id="queryStudentByStuNo" parameterType="int" resultType="com.entity.Student">


select * from student where id = ${stuNo}


</select>


<insert id="addStudent" parameterType="com.entity.Student">


insert into student(id,name,age) values (#{id},#{name},#{age})


</insert>


</mapper>


(一)mybatis 中 #和 $的区别




1、#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。


如:where id=#{id},如果传入的值是 1,那么解析成 sql 时的值为 where id="1",?如果传入的值是 id,则解析成的 sql 为 where id="id"。


2、$将传入的数据直接显示生成在 sql 中。


如:where id=${id},如果传入的值是 1,那么解析成 sql 时的值为 where username=1;


如果传入的值是;drop table user;,则解析成的 sql 为:select *?from student?where id=1;drop table student;


3、#方式能够很大程序防止 sql 注入,$方式无法防止 sql 注入。

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
【MyBatis 1】SQL注入,Java技术功底不够如何去面试