PHP开发中值得注意的几个问题(三)
作者:admin 日期:2012-04-07
1.md5
当内容为空时,md5空内容后也是有值的
md5(''):d41d8cd98f00b204e9800998ecf8427e
2.关于特殊字符转换
$str = "<strong>abcd\"</strong>";
$str = htmlspecialchars($str);
echo $str;
write_file('debug.log', $str);
?>
<textarea name="text" rows="5" cols="30"><?php echo $str;?></textarea>
页面输出如下:
<strong>abce"</strong>
当然textarea里面的内容也是<strong>abce"</strong>
查看页面的源代码如下(为了防止页面乱码或错乱,所以需要将内容转换一下[如将<转换为<,>转换为>],提交之后还需要转换一下[如将<转换为<,>转换为>],得到原始的数据,如<strong>abcd\"</strong>):
<strong>abce"</strong><textarea name="text" rows="5" cols="30"><strong>abce"</strong></textarea>
将变量$str的值保存在文件debug.log中,内容如下
<strong>abce"</strong>
3.关于addslashes
$data = array("a\"", "b\"", "c\"");
//addslashes($data, 1);
print_r($data);
如果没有上述addslashes那行代码,则输出Array ( [0] => a" [1] => b" [2] => c" )
否则输出Array ( [0] => a\" [1] => b\" [2] => c\" )
4.不同编码的汉字在urlencode后的内容是不同的
a.如果字符串内容是数字或字母,则utf8编码以后内容不变
b.
/*
关于中文urlencode测试
下面的例子输出如下:
basketball(gb2312):%C0%BA%C7%F2
basketball(utf-8):%E7%AF%AE%E7%90%83
在六间房输入关键字篮球时的url地址,参数k的值是utf8编码的汉字urlencode以后的内容
http://6.cn/search.php?k=%E7%AF%AE%E7%90%83&t=v
通过此例可以说明一个问题,即不同编码的字符经过urlencode处理以后的结果是不相同的,进行测试时此文件内容本身的编码为utf8
*/
$str = '篮球';
echo "basketball(gb2312):" . urlencode($str) . NEWLINE;
echo "basketball(utf-8):" . urlencode(iconv('gb2312', 'utf-8', $str)) . NEWLINE;
5.php文件上传中的错误代码
上传文件的时候要注意一下这些错误代码
错误信息说明
从 PHP 4.2.0 开始,PHP 将随文件信息数组一起返回一个对应的错误代码。该代码可以在文件上传时生成的文件数组中的 error 字段中被找到,也就是 $_FILES['userfile']['error']。
UPLOAD_ERR_OK
其值为 0,没有错误发生,文件上传成功。
UPLOAD_ERR_INI_SIZE
其值为 1,上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值。
UPLOAD_ERR_FORM_SIZE
其值为 2,上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。
UPLOAD_ERR_PARTIAL
其值为 3,文件只有部分被上传。
UPLOAD_ERR_NO_FILE
其值为 4,没有文件被上传。
UPLOAD_ERR_NO_TMP_DIR
其值为 6,找不到临时文件夹。PHP 4.3.10 和 PHP 5.0.3 引进。
UPLOAD_ERR_CANT_WRITE
其值为 7,文件写入失败。PHP 5.1.0 引进。
注: 以上值在 PHP 4.3.0 之后变成了 PHP 常量。
6.关于函数的定义
switch ($act) {
case 'log':
get_log();
break;
}
if ($act == 'log') {
function get_log() {
//do something
}
}
会报函数get_log没有定义的错误
把
if ($act == 'log') {
function get_log() {
//do something
}
}
改为
function get_log() {
//do something
}
就不报错了,暂时不知道为什么会这样?
7.关于error_reporting
在公共的包含文件中最好有error_reporting(E_ALL & ~E_NOTICE),这样不管php.ini的配置是怎样的,都不会报E_NOTICE级别的错误。
8.XSS攻击判断
可以参考我以前写的,简单的写了一下
9.SQL注入
SQL注入用通俗一点的说法理解就是,你的程序中的sql语句是动态组成的,其中部分内容接收用户输入的参数,如果你没有对用户输入的参数进行过滤及校验,则有可能利用你程序的漏洞获取你数据库中的一些信息,对公司造成损失。
可以用mysql_escape_string或mysql_real_escape_string过滤一下用户输入的参数,这样就相对比较安全了。
mysql_escape_string
*******************************************
由于 mysql_real_escape_string 需要 MySQL 数据库连接,因此,在调用 mysql_real_escape_string 之前,必须连接上 MySQL 数据库。
注意!mysql_real_escape_string 必须在(PHP 4 >= 4.3.0, PHP 5)的情况下才能使用。否则只能用 mysql_escape_string ,两者的区别是:
mysql_real_escape_string 考虑到连接的当前字符集,而mysql_escape_string 不考虑。
This function will escape the unescaped_string , so that it is safe to place it in a mysql_query(). This function is deprecated.
This function is identical to mysql_real_escape_string() except that mysql_real_escape_string() takes a connection handler and escapes the string according to the current character set. mysql_escape_string() does not take a connection argument and does not respect the current charset setting.
Example #1 mysql_escape_string() example
<?php
$item = "Zak's Laptop";
$escaped_item = mysql_escape_string($item);
printf("Escaped string: %s\n", $escaped_item);
?>
The above example will output:
Escaped string: Zak\'s Laptop
详细看这儿:http://cn.php.net/manual/en/function.mysql-escape-string.php
*******************************************
mysql_real_escape_string
*******************************************
Escapes special characters in the unescaped_string , taking into account the current character set of the connection so that it is safe to place it in a mysql_query(). If binary data is to be inserted, this function must be used.
mysql_real_escape_string() calls MySQL's library function mysql_real_escape_string, which prepends backslashes to the following characters: \x00, \n, \r, \, ', " and \x1a.
This function must always (with few exceptions) be used to make data safe before sending a query to MySQL.
Examples
Example #1 Simple mysql_real_escape_string() example
<?php
// Connect
$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password')
or die(mysql_error());
// Query
$query = sprintf("Select * FROM users Where user='%s' AND password='%s'",
mysql_real_escape_string($user),
mysql_real_escape_string($password));
?>
Example #2 An example SQL Injection Attack
<?php
// Query database to check if there are any matching users
$query = "Select * FROM users Where user='{$_POST['username']}' AND password='{$_POST['password']}'";
mysql_query($query);
// We didn't check $_POST['password'], it could be anything the user wanted! For example:
$_POST['username'] = 'aidan';
$_POST['password'] = "' or ''='";
// This means the query sent to MySQL would be:
echo $query;
?>
The query sent to MySQL:
Select * FROM users Where user='aidan' AND password='' or ''=''
This would allow anyone to log in without a valid password.
Example #3 A "Best Practice" query
Using mysql_real_escape_string() around each variable prevents SQL Injection. This example demonstrates the "best practice" method for querying a database, independent of the Magic Quotes setting.
<?php
if (isset($_POST['product_name']) && isset($_POST['product_description']) && isset($_POST['user_id'])) {
// Connect
$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password');
if(!is_resource($link)) {
echo "Failed to connect to the server\n";
// ... log the error properly
} else {
// Reverse magic_quotes_gpc/magic_quotes_sybase effects on those vars if ON.
if(get_magic_quotes_gpc()) {
$product_name = stripslashes($_POST['product_name']);
$product_description = stripslashes($_POST['product_description']);
} else {
$product_name = $_POST['product_name'];
$product_description = $_POST['product_description'];
}
// Make a safe query
$query = sprintf("Insert INTO products (`name`, `description`, `user_id`) VALUES ('%s', '%s', %d)",
mysql_real_escape_string($product_name, $link),
mysql_real_escape_string($product_description, $link),
$_POST['user_id']);
mysql_query($query, $link);
if (mysql_affected_rows($link) > 0) {
echo "Product inserted\n";
}
}
} else {
echo "Fill the form properly\n";
}
?>
The query will now execute correctly, and SQL Injection attacks will not work.
详细看这儿:http://cn.php.net/manual/en/function.mysql-real-escape-string.php
*******************************************
详细的可以看下面的文章
SQL注入百度百科: http://baike.baidu.com/view/3896.htm
SQL注入专题:http://www.secnumen.com/technology/anquanwenzhai.htm
10.关于文件操作权限问题
a.rename时如果目标文件已经存在,则会报错,所以要先删除
if (file_exists($newName)) @unlink($newName);
$ret = rename($dest_file, $newName);
b.在windows操作系统下如果文件已经用fopen等打开,则必须用fclose关闭此文件对应的文件指针才能进行rename,unlink等操作,否则会报permission denied的错误
if (!($fp = fopen($filename, $mode))) {
die(sprintf("Mode:|%s|, open file:|%s| failed!", $mode, $filename));
return false;
}
if ($mode == "w") {
$tmpFile = $filename . ".new";
$fpNew = @fopen($tmpFile, $mode);
if (@fwrite($fpNew, $content)) {
if ($fp) @fclose($fp);
if ($fpNew) fclose($fpNew);
if (file_exists($filename)) unlink($filename);
rename($tmpFile, $filename);
} else {
die(sprintf("Mode:|%s|, write content:|%s| to file:|%s| failed!", $mode, $content, $filename));
}
} else {
flock($fp, LOCK_EX);
if (!@fwrite($fp, $content)) {
die(sprintf("Mode:|%s|, write content:|%s| to file:|%s| failed!", $mode, $content, $filename));
return false;
}
@chmod($sTempFile, 0777);
flock($fp, LOCK_UN);
}
if ($fp) @fclose($fp);
c.2009/12/2 在windows操作系统下,如果某文件被某编辑器打开,此时执行某个php程序时要往此文件中写日志,则打开此文件时就报错,无法写入,真是有点奇怪。我回到家测试后这种情况又不报错了,奇怪,难道跟环境有关吗?
2009.12.21更新:
当用editplus打开某文件,而当有程序要往此文件中写入内容,则无法写入,应该是editplus将此文件锁定了,不让其它的程序写入,而如果用UltraEdit打开此文件,则不存在此问题,可以正常写入。
下一篇: PHP开发中值得注意的几个问题(二)
文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: php
相关日志:
广告位