PHP 数据清洗

13

我刚接触编码和 PHP,想学习什么是最好的方式来清理表单数据以避免页面格式错误、代码注入等问题。下面找到的示例脚本是一个好的例子吗?

代码最初发布在 http://codeassembly.com/How-to-sanitize-your-php-input/

/**
 * Sanitize only one variable .
 * Returns the variable sanitized according to the desired type or true/false 
 * for certain data types if the variable does not correspond to the given data type.
 * 
 * NOTE: True/False is returned only for telephone, pin, id_card data types
 *
 * @param mixed The variable itself
 * @param string A string containing the desired variable type
 * @return The sanitized variable or true/false
 */

function sanitizeOne($var, $type)
{       
    switch ( $type ) {
    case 'int': // integer
        $var = (int) $var;
        break;

    case 'str': // trim string
        $var = trim ( $var );
        break;

    case 'nohtml': // trim string, no HTML allowed
        $var = htmlentities ( trim ( $var ), ENT_QUOTES );
        break;

    case 'plain': // trim string, no HTML allowed, plain text
        $var =  htmlentities ( trim ( $var ) , ENT_NOQUOTES )  ;
        break;

    case 'upper_word': // trim string, upper case words
        $var = ucwords ( strtolower ( trim ( $var ) ) );
        break;

    case 'ucfirst': // trim string, upper case first word
        $var = ucfirst ( strtolower ( trim ( $var ) ) );
        break;

    case 'lower': // trim string, lower case words
        $var = strtolower ( trim ( $var ) );
        break;

    case 'urle': // trim string, url encoded
        $var = urlencode ( trim ( $var ) );
        break;

    case 'trim_urle': // trim string, url decoded
        $var = urldecode ( trim ( $var ) );
        break;

    case 'telephone': // True/False for a telephone number
        $size = strlen ($var) ;
        for ($x=0;$x<$size;$x++)
        {
            if ( ! ( ( ctype_digit($var[$x] ) || ($var[$x]=='+') || ($var[$x]=='*') || ($var[$x]=='p')) ) )
            {
                return false;
            }
        }
        return true;
        break;

    case 'pin': // True/False for a PIN
        if ( (strlen($var) != 13) || (ctype_digit($var)!=true) )
        {
            return false;
        }
        return true;
        break;

    case 'id_card': // True/False for an ID CARD
        if ( (ctype_alpha( substr( $var , 0 , 2) ) != true ) || (ctype_digit( substr( $var , 2 , 6) ) != true ) || ( strlen($var) != 8))
        {
            return false;
        }
        return true;
        break;

    case 'sql': // True/False if the given string is SQL injection safe
        //  insert code here, I usually use ADODB -> qstr() but depending on your needs you can use mysql_real_escape();
        return mysql_real_escape_string($var);
        break;
    }       
    return $var;
}

看起来很有用。虽然htmlentities应该被替换为htmlspecialchars并声明字符集参数。 - mario
4个回答

18

这个脚本有一些很好的功能,但它在消毒方面做得不够好!

根据您的需要(和想要接受的内容),您可以使用以下方法:

  • abs() 用于正数(注意它也接受浮点数)

  • preg_replace('/[^a-zA-Z0-9 .-]/','',$var) 用于从字符串中清除任何特殊字符或 preg_replace('/\D/','',$var) 用于删除所有非数字字符

  • ctype_* 函数,例如ctype_digit($var)

  • filter_var()filter_input() 函数

  • 类型转换,例如 (int)$_GET['id']

  • 转换,例如 $id=$_GET['id']+0;


1
谢谢。使用正则表达式来删除特殊字符是否更好?为什么不使用htmlspecialchars? - PeanutsMonkey

10

你的示例脚本不太好 - 所谓的字符串净化只是修剪每个端点处的空格。依赖它会让你很快陷入麻烦。

没有一种通用的解决方案。您需要为您的应用程序应用正确的净化方法,这完全取决于您需要的输入及其使用位置。而且,在任何情况下都应该在多个级别进行净化 - 最可能是在接收数据时,存储数据时以及可能在呈现数据时。

值得阅读,可能有相似内容:

What's the best method for sanitizing user input with PHP?

Clean & Safe string in PHP


谢谢。您如何测试所有可能的情况,或者至少是其中的一个子集? - PeanutsMonkey
@PeanutsMonkey - 你的示例中使用的方法是好的 - 即调用一个通用的清理函数,该函数仅接受您明确定义的数据,并具有您明确定义的类型。这部分很好。问题在于清理需要足够强大。清理数字很容易(类似 $i = (float) $i;),但通常字符串存在问题,因为它们容易受到SQL注入和XSS攻击的影响。但是,您确实需要知道您的字符串将用于什么目的。例如,它们必须支持外语字符吗? - Oliver Emberton

7

4

这不错。

对于SQL,最好避免所有风险,使用PDO将参数插入到查询中。


你可以使用mysqli来实现同样的功能。如果你只会使用MySQL,那么这可能会稍微好一些。mysqli预处理语句 - Lightbulb1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接