PHP开发中值得注意的几个问题(三)

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>
查看页面的源代码如下(为了防止页面乱码或错乱,所以需要将内容转换一下[如将<转换为&lt;,>转换为&gt;],提交之后还需要转换一下[如将&lt;转换为<,&gt;转换为>],得到原始的数据,如<strong>abcd\"</strong>):
&lt;strong&gt;abce&quot;&lt;/strong&gt;<textarea name="text" rows="5" cols="30">&lt;strong&gt;abce&quot;&lt;/strong&gt;</textarea>

将变量$str的值保存在文件debug.log中,内容如下
&lt;strong&gt;abce&quot;&lt;/strong&gt;

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打开此文件,则不存在此问题,可以正常写入。
 



[本日志由 admin 于 2012-04-17 12:22 AM 更新]
上一篇: PHP中文件上传时的注意事项
下一篇: PHP开发中值得注意的几个问题(二)
文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: php
相关日志:
评论: 0 | 引用: 0 | 查看次数: 1780
发表评论
昵 称:
密 码: 游客发言不需要密码.
邮 箱: 邮件地址支持Gravatar头像,邮箱地址不会公开.
网 址: 输入网址便于回访.
内 容:
验证码:
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.
字数限制 1000 字 | UBB代码 开启 | [img]标签 关闭

 广告位

↑返回顶部↑