单双引号魔术引用详解,让用户提交的数据更安全
在项目开发中,我们会从客户端接受用户提交发送的数据,经过处理后保存到数据库的相应表格中。
这个过程中,有一个隐藏的安全性问题,这就是数据库SQL语句的引号引用处理。
如果此时$postVar_1和$getVar_2变量都是来自客户端提交的数据,那么这时隐藏的安全性问题就有可能危及数据服务器的安全。
例如:通常我们刚接触PHP的同学在书写代码中接受提交参数时,会写成
- $postVar_1 = $_POST['var_1'];
- $getVar_2 = $_GET['var_2'];
下面我们分析两个SQL语句,看看是否存在安全性问题:
- SQL1: insert into tableName set col_1='$postVar_1';
- SQL2: insert into tableName set col_2="$getVar_2";
注意:
若用户在表单中var_1处填写的数据为:I’m fine!
若用户在表单中var_2处填写的数据为:This is “BUG”!
当我们只是简单的将这两个数据接受到变量中,并传入上面的SQL语句中就会出现,致命的SQL语句执行错误。
我们把数据代入SQL,看看究竟错误在哪里
- SQL1: insert into tableName set col_1='I'm fine!';
- SQL2: insert into tableName set col_2='This is "BUG"";
可以看出,单引号和双引号此时已经匹配的混乱了,用户提交的传入变量数据和SQL语句中用于字段值定界符的单双引号产生了混淆,若把这样的SQL语句放到执行过程中去,那么必定会报错,严重的会被人利用,攻破服务器的安全防护。
所以我们需要对此情况加以判别和处理,所以我们要对传入的参数进行单双引号的引用过滤解析,这就要用到我们之前学习过的一个非常简单的函数——addslashes:
我们把接受数据到变量的过程重新用addslashes做一遍单双引号的过滤解析后,再传递给SQL语句,那就是安全的了:
- $postVar_1 = addslashes($_POST['var_1']);
- $getVar_2 = addslashes($_GET['var_2']);
若还是上次输入的变量值,此时的SQL语句已经变为
- SQL1: insert into tableName set col_1='I\'m fine!';
- SQL2: insert into tableName set col_2='This is \"BUG\"";
- ?>
可见单双引号前都被加入了一个反斜杠,用以表明反斜杠之后的字符为单纯的字面意义,不再表示为引号的作用,就不会与SQL语句中的单双引号产生混淆了。
这样用的多了,必然会比较辛苦,让我们的程序中充满了addslashes这样的函数,为了偷懒,开发者想出一个办法,让PHP自动对所有用户提交的数据变量的值,都自动的进行单双引号的过滤解析,这就是单双引号的魔术引用。
哪些数据是属于魔术引用自动处理的范围呢?主要有三种来自用户提交的数据:
* $_POST:通过表单post发送的数据
* $_GET:通过URL地址传递的数据
* $_COOKIE:通过客户端浏览器cookie传递的数据
以上三种数据在一起简称为GPC,这下大家知道了把,其实就是三种变量的首字母简称大写组成。
魔术引用的开启和关闭是由php的配置文件php.ini来控制的,我们在其中搜索:magic_quotes_gpc可以查看到当前是否为off或on。
当然,你并不一定拥有自己的服务器,或者有足够的权限去修改php.ini这个配置文件(例如你租的只是虚拟空间),那么就无法自由控制魔术引用的开合关闭了,在代码中如何判别呢?通过get_magic_quotes_gpc(),这个函数的返回值,我们就可以知道当前php.ini中的当前魔术引用的开关状态。
再把魔术引用的开合关闭考虑到我们的代码中来,我们就发现原生态的php函数addslashes就不方便了,因为若服务器已经开启了魔术引用,我们再人工做转义解析,就多此一举了。反而会让addslashes产生的反斜杠多余,为此,我们需要自定义一个函数,首先来判断是否开启了魔术引用。
若开启,则不做任何转义解析操作;若未开启,则人工通过addslashes加上反斜杠进行转义解析。
- //自定义的addslashes函数
- function add_slashes($str) {
- if(get_magic_quotes_gpc()) {
- return $str;
- }else{
- return addslashes($str);
- }
- }
以后在代码中直接调用该函数就可以放心的使用了。但还是不够方便,他只是自动区分了魔术引用的开启和关闭,并没有减少代码中调用函数的次数,每次接受数据仍然要调用该函数,没有达到缩减代码的目的。为此,我们需要更高级的方法来对GPC变量进行解析转义操作,这就要考虑到GPC变量的特征了,三个全局变量数组,如果做呢?下面给出终极解决方案,数组的变量,以及函数的迭代调用。
- function add_slashes($string, $force = 0) {
- if(!get_magic_quotes_gpc() || $force) {
- if(is_array($string)) {
- foreach($string as $key => $val) {
- $string[$key] = add_slashes($val, $force);
- }
- } else {
- $string = addslashes($string);
- }
- }
- return $string;
- }
- $_POST=add_slashes($_POST);
- $_GET=add_slashes($_GET);
- $_COOKIE=add_slashes($_COOKIE);
把这段代码放到程序的入口处,就可以将GPC三个全局变量中的所有元素都自动的根据魔术引用的状态,适当的进行单双引号的转义解析了。
好了,说了这么多,其实原理很简单,总结一下:
1、首先判断是否开启魔术引用
2、根据魔术引用状态,适当的做单双引号的解析转义处理
3、若为数组,则遍历数组元素,迭代调用自定义函数
