php中有关操作数据库安全的几个函数总结(干货)
当使用php向数据库中写入或者读取数据时,若在进行操作前对字符串进行一些处理,如:过滤处理,可能会导致某些数据库语句因为特殊的字符引起的污染而出现致命的错误。为此,php中提供了一个“魔法开关”—–magic_quotes_gpc。(该开关已在5.4.0版本被删除,始终置为off)
当magic_quotes_gpc = on时,从外部post、get、cooki过来的数据都会在预定义字符之前添加”\“。
比如:
程序中var_dump($_GET[‘id’]);
输出的结果为:
string(3) “1\’”
预定义的字符为:
单引号(‘) 双引号(”) 反斜杠(\) NULL
当magic_quotes_gpc=off时,写入数据库的字符串未经过任何过滤处理,从数据库中读出的字符串也未作任何处理。如何这样设置这个开关,并且没有其他对字符串进行处理的操作,那么可能会给数据库的读写带来问题,例如:
将数据:$data = “insert_data’”to_mysal”;(data和to之间是一个单引号,一个双引号)
若将字符串$data写入数据库中,则会出现sql语句错误,写入数据失败。
那么如果不使用这个“开关”就没有办法解决这个问题了吗?答案是否定的。
我们可以使用以下方法:
使用addslashes() 函数
函数原型:
string addslashes ( string $str )
参数:要转义的字符串
返回值:返回转义后的字符串
作用:将要转义的字符串中的预定义字符转义,即在预定义字符前面加上反斜杠。
php中还有一个函数能转义sql语句中使用的字符串中特殊的字符,该函数的原型如下:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier = NULL ] )
本函数将 unescaped_string 中的特殊字符转义,并计及连接的当前字符集,因此可以安全用于 mysql_query()。
现在向数据库中插入数据的可能会引起sql语句被污染的问题已经解决了,可是如果现在想要把刚才添加到数据库中的元素读取出来的话,会发现读出的数据中每个预定义的字符前面都多了一个反斜杠,这时反斜杠并不是我们想要的,那么有没有办法将每个预定义字符前面的反斜杠去掉呢?
php中也提供了具有该功能的函数:
函数原型为:
string stripslashes ( string $str );
函数返回值:返回一个去掉转义反斜杠的字符串,即去掉addslashes()函数添加的字符串。
另外tp中自定义了一个函数:
function stripslashes_deep($value) { $value = is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value); return $value; }
这个函数也能去除预定义字符前的反斜杠。
现在还有一个问题:在访问服务器之前,我们并不知道“魔法开关”的状态是打开还是关闭,如果已经处于打开状态,再使用addslashes()函数进行转义,就会使预定义前面有两个反斜杠,从而使的写入数据库的数据发生改变。
解决办法:
可以使用函数get_magic_quotes_gpc()进行检验“魔法开关”是否打开。
$data = get_magic_quotes_gpc() ? $data : addslashes($data);
预防数据库攻击的方法:
<?php function check_input($value) { // 去除斜杠 if (get_magic_quotes_gpc()) { $value = stripslashes($value); } // 如果不是数字则加引号 if (!is_numeric($value)) { $value = “‘” . mysql_real_escape_string($value) . “‘”; } return $value; } $con = mysql_connect(“localhost”, “hello”, “321″); if (!$con) { die(‘Could not connect: ‘ . mysql_error()); } // 进行安全的 SQL $user = check_input($_POST['user']); $pwd = check_input($_POST['pwd']); $sql = “SELECT * FROM users WHERE user=$user AND password=$pwd”; mysql_query($sql); mysql_close($con); ?>
上一篇: Java并发编程:线程池的使用(转载)