php中mysql_real_escape_string函数是一个用于转义SQL查询中字符串特殊字符的函数,目的是为了防止SQL注入攻击。在Web开发中,通过用户输入构造SQL查询是非常常见的情况,然而恶意用户可能通过输入特殊格式的数据,来干扰SQL语句的正常执行,甚至读取或修改数据库中的信息,这就是SQL注入攻击。
为了防范这种攻击,开发者需要确保用户输入的数据在插入SQL语句之前被适当处理。mysql_real_escape_string函数通过在某些特殊字符前加上反斜杠(\)来转义这些字符。这些被转义的特殊字符包括:
- \x00(ASCII为零字符)
- \n(换行符)
- \r(回车符)
- \(反斜杠)
- '(单引号)
- "(双引号)
- \x1a(ASCII为26字符)
函数的基本用法是:
```php
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
```
其中,$unescaped_string参数是需要被转义的字符串,而可选的第二个参数(link_identifier)是数据库连接标识,如果没有指定,默认使用上一个打开的数据库连接。
当调用成功时,mysql_real_escape_string返回转义后的字符串,如果连接失效,则返回false。
接下来我们来看几个实际的使用例子。
例子1:
```php
$con=mysql_connect("localhost","hello","321");
if(!$con)
{
die('Could not connect:'.mysql_error());
}
// 获得用户名和密码的代码
// 转义用户名和密码,以便在SQL中使用
$user=mysql_real_escape_string($user);
$pwd=mysql_real_escape_string($pwd);
$sql="SELECT * FROM users WHERE user='$user' AND password='$pwd'";
// 更多代码
mysql_close($con);
```
在例子1中,用户输入的用户名和密码通过mysql_real_escape_string函数进行转义,然后安全地用于SQL查询。
例子2演示了不使用mysql_real_escape_string函数可能造成的安全漏洞:
```php
$sql="SELECT * FROM users WHERE user='{$_POST['user']}' AND password='{$_POST['pwd']}'";
mysql_query($sql);
// 不检查用户名和密码
// 可以是用户输入的任何内容,比如:
$_POST['user']='john';
$_POST['pwd']='\'OR\'\'=\'';
```
在这种情况下,如果用户输入“'OR'='”,那么SQL查询就会变成:
```sql
SELECT * FROM users WHERE user='john' OR ''='
```
这会导致攻击者无需输入密码即可登录系统。
例子3展示了如何正确地使用函数来预防数据库攻击:
```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;
}
// 进行安全的SQL
$user=check_input($_POST['user']);
$pwd=check_input($_POST['pwd']);
$sql="SELECT * FROM users WHERE user=$user AND password=$pwd";
mysql_query($sql);
```
在例子3中,创建了一个check_input函数,它对输入的值进行了清理和转义,然后在构建SQL查询时使用了返回的值。这样可以确保所有的输入都经过了适当的处理,从而有效地防止了SQL注入攻击。
需要注意的是,mysql_real_escape_string函数是针对MySQL数据库的,且使用旧式的mysql扩展,这种扩展已经不被推荐使用了。PHP5.5.0之后的版本中,mysql扩展已被废弃,并在PHP7.0.0中被移除。目前推荐使用PDO或mysqli扩展,这两个扩展都提供了更好的性能和安全性。如果在使用新的扩展,应使用mysqli_real_escape_string函数或者PDO提供的预处理语句和参数绑定来预防SQL注入。