一次由北哥QQ群成员提问引发的技术分享 - 说说yii2的emulatePrepare=true
2017-04-10 19:27
183 查看
大家知道北哥最近搞了QQ群,本着打造最严谨技术QQ群的理念,有群友提了问题怎么能不写篇文章分享下~
我们都知道在Yii2的数据库配置中有一项叫做emulatePrepare
很多同学都知道这其实是一个PDO的属性,代表PDO::ATTR_EMULATE_PREPARES - 是否启用预处理,我们yii默认为null,表示默认PDO对该属性当前的设置,不做处理。当然你可以像上面配置文件一样人为的指定该值为true / false。
关于yii对 emulatePrepare 的处理我们可以在Connection类中轻松发现,它仅仅是yii是否开启PDO::ATTR_EMULATE_PREPARES 的一个开关而已,如下图所示:
因此我们研究的核心问题就回到 PDO的ATTR_EMULATE_PREPARES到底能起到什么作用的问题上来了?
我们先列目录
为何预处理能防止SQL注入
ATTR_EMULATE_PREPARES
推荐的策略
Begin...
拿mysql为例,第一步是prepare阶段,发送带有占位符的sql语句到mysql服务器,然后就可以多次发送占位符参数给mysql服务器进行执行,参数将会被当作普通字符处理。这就相当于我们为一个函数传参数一样,参数不会再去影响整个sql的构成。因此直接屏蔽了所有的SQL注入问题。
但是,并不是所有的数据库都支持预处理,否则也不需要ATTR_EMULATE_PREPARES 出马了~~
当我们将ATTR_EMULATE_PREPARES 设置为 true时,PDO开始模拟预处理机制,要记住,这些是PDO自己的事情,和数据库没有半毛钱关系,换句话说,数据库收到的仍然是一个字符串拼凑好的SQL语句。
在PHP5.3.8之前,PDO预处理也存在着因字符类型不同而被注入的问题,因此很多人是不推荐的,现在已经没事了。
那么你肯定要问了,既然都很安全,到底是PDO的好还是数据库自己的好那?
我们还是以MySQL为例
PDO的预处理一次发送完整的sql给mysql执行,不需要MySQL做额外处理(如保存会话状态等),因此性能比较好一些,而使用MySQL预处理则需要多次发送,MySQL服务器需要保存会话状态,性能上会有一些损耗。PDO > MySQL
MYSQL预处理在prepare阶段就能检测出sql语句的错误,而使用PDO的预处理方式制定在exec阶段才能发现(因为模拟方式拼接好sql在exec阶段才会发送到MySQL服务器)。PDO < MySQL
且如果你在同一次数据库连接会话中执行同样的语句许多次,它将只被解析一次,这可以提升一点执行速度。PDO < MySQL
基于上面理由,我们推荐你优先使用数据库自身的预处理,大家也都是这样干的~
因此一个更牛逼的配置出现了,见下文。
但是此false非彼false。
当你设置了ATTR_EMULATE_PREPARES = false时,的确我们会采用数据库的预处理,但是PHP知道安全才是第一位的,因此即便你设置了false,当数据库自己的预处理突然抽风不好用了的时候,PDO并没有放弃,而是立刻启动自身的模拟预处理,保障数据的安全性。
对了,就是false,false,false。
不知道你是否听懂~~~
北哥兄弟连 yii2干货和原创视频 http://nai8.me/
我们都知道在Yii2的数据库配置中有一项叫做emulatePrepare
return [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=yii-study.local.com', 'username' => 'root', 'password' => '', 'charset' => 'utf8', 'emulatePrepare'=>true ];
很多同学都知道这其实是一个PDO的属性,代表PDO::ATTR_EMULATE_PREPARES - 是否启用预处理,我们yii默认为null,表示默认PDO对该属性当前的设置,不做处理。当然你可以像上面配置文件一样人为的指定该值为true / false。
关于yii对 emulatePrepare 的处理我们可以在Connection类中轻松发现,它仅仅是yii是否开启PDO::ATTR_EMULATE_PREPARES 的一个开关而已,如下图所示:
因此我们研究的核心问题就回到 PDO的ATTR_EMULATE_PREPARES到底能起到什么作用的问题上来了?
我们先列目录
为何预处理能防止SQL注入
ATTR_EMULATE_PREPARES
推荐的策略
Begin...
为何预处理能防止SQL注入
我们都知道,SQL注入是通过触发脚本在构造SQL语句时包含恶意的字符串,而数据库预处理机制就是为了解决此危险而诞生的,数据库的预处理一般分为两步拿mysql为例,第一步是prepare阶段,发送带有占位符的sql语句到mysql服务器,然后就可以多次发送占位符参数给mysql服务器进行执行,参数将会被当作普通字符处理。这就相当于我们为一个函数传参数一样,参数不会再去影响整个sql的构成。因此直接屏蔽了所有的SQL注入问题。
但是,并不是所有的数据库都支持预处理,否则也不需要ATTR_EMULATE_PREPARES 出马了~~
ATTR_EMULATE_PREPARES
ATTR_EMULATE_PREPARES代表是否启用PDO自身的模拟预处理,因为总有些数据库是很另类的不支持预处理的,但是我们为了安全,PDO就决定老哥自己来模拟预处理的机制。当我们将ATTR_EMULATE_PREPARES 设置为 true时,PDO开始模拟预处理机制,要记住,这些是PDO自己的事情,和数据库没有半毛钱关系,换句话说,数据库收到的仍然是一个字符串拼凑好的SQL语句。
在PHP5.3.8之前,PDO预处理也存在着因字符类型不同而被注入的问题,因此很多人是不推荐的,现在已经没事了。
那么你肯定要问了,既然都很安全,到底是PDO的好还是数据库自己的好那?
我们还是以MySQL为例
PDO的预处理一次发送完整的sql给mysql执行,不需要MySQL做额外处理(如保存会话状态等),因此性能比较好一些,而使用MySQL预处理则需要多次发送,MySQL服务器需要保存会话状态,性能上会有一些损耗。PDO > MySQL
MYSQL预处理在prepare阶段就能检测出sql语句的错误,而使用PDO的预处理方式制定在exec阶段才能发现(因为模拟方式拼接好sql在exec阶段才会发送到MySQL服务器)。PDO < MySQL
且如果你在同一次数据库连接会话中执行同样的语句许多次,它将只被解析一次,这可以提升一点执行速度。PDO < MySQL
基于上面理由,我们推荐你优先使用数据库自身的预处理,大家也都是这样干的~
因此一个更牛逼的配置出现了,见下文。
推荐的策略
为何是牛逼的策略那,按照你的理解,如果我们优先使用数据库预处理是不是要 ATTR_EMULATE_PREPARES = false操作。但是此false非彼false。
当你设置了ATTR_EMULATE_PREPARES = false时,的确我们会采用数据库的预处理,但是PHP知道安全才是第一位的,因此即便你设置了false,当数据库自己的预处理突然抽风不好用了的时候,PDO并没有放弃,而是立刻启动自身的模拟预处理,保障数据的安全性。
'emulatePrepare'=>false
对了,就是false,false,false。
不知道你是否听懂~~~
北哥兄弟连 yii2干货和原创视频 http://nai8.me/
相关文章推荐
- 由12306.cn引发的网站性能技术思考。大家还什么想法说说!
- 四、成员方法、构造方法、普通代码块、构造代码块、静态代码块应用技术分享
- [技术分享] Forefront 家族又添新成员: Forefront Online Protection for Exchange
- 分享 原创的一个模拟鼠标键盘操作的 设置简单 示例可以模拟向QQ群,以及QQ群内成员发送信息。
- 记一次和阿里某总监对话引发的思考:说说你框架的设计思路和优点亮点!
- 记一次和阿里某总监对话引发的思考:说说你框架的设计思路和优点亮点!
- 如何做好一次知识或技术分享
- 【基于node.js+express的web开发备忘】--技术分享(TShare)站点-提问模块
- 记录经理的一次网站安全与网站优化的技术分享会议
- 由 '' in 'abc' return True 引发的思考----Python 成员测试操作
- win环境 yii2 框架 overtrue/wechat 包 由 sys_get_temp_dir 引发的 the directory "c:\Windows" is not writable
- 一次修改mysql字段类型引发的技术探究
- 一个合作良好的团队里,对于团队成员来说重要的不是垄断技术,而是分享技术的同时做到比其他成员的技术好,做领跑者,而不是垄断者。
- 网易视频云技术分享:记一次.gitignore的操作细节
- 网易技术分享:Nginx缓存引发的跨域惨案
- 记一次和阿里某总监对话引发的思考:说说你框架的设计思路和优点亮点!
- 说说我眼中中法技术人员的差异【转】
- 说说我眼中中法技术人员的差异
- 网络技术引发的软件产业蜕变
- 关于在网页中使用IP的一次技术讨论