有什么方法可以改进我的PHP数据卫生课程?

时间:2011-02-16 21:56:21

标签: php sql security class sanitization

我正在组建一个网站,(我们已经在客户端使用javascript进行预验证)。但是厌倦了每隔一行编写mysql_real_escape_string。我写了这个类只有两个函数,主要集中在用户输入/ sql中清理数据。我的问题是,有哪些方法可以实现更轻松的输入消毒并提高代码可读性?

<?php 
class Safe {
    function userinput($string){
        $string = strip_tags($string);
        $string = htmlspecialchars($string);
        return $string;
    }
    function sql ($string){
       $sqlstuff = Array("union", "select", "update", "delete", "outfile", "create");
       $string = Safe::str($string);
       $string = mysql_escape_string($string);
       $string = str_ireplace($sqlstuff, "", $string);
       return $string;

    }
}
?>

3 个答案:

答案 0 :(得分:5)

对不起,这听起来很刺耳,但是你的班级完全被打破了。

  • 您不应该使用htmlspecialchars来清理输入,它只对转义输出有用。您不需要编码HTML以插入数据库也不需要。仅在向浏览器发送输出时使用htmlspecialchars
  • 您不应该从输入中删除标记,您应该在以后输出该数据时使用htmlspecialchars将它们单独留下以确保HTML标记被转义而不被浏览器解释
  • 您不应该使用mysql_escape_stringmysql_real_escape_string,您应该使用PDO。如果您正在编写新网站,绝对没有理由无法正确启动并使用PDO。 做到
  • 你不应该过滤掉“联盟”,“选择”等等,这是愚蠢的。这些单词可以用普通英语出现,如果你正确地转发PDO会为你处理的引号,它们就是无害的。

再次,抱歉这个答案的严厉语气,但废弃整个事情并使用PDO。这里几乎没有任何可以挽救的东西。

答案 1 :(得分:2)

使用类似的类是个好主意,特别是如果它简化了输入处理。不过我想评论几点:

  • 您应该使用mysql_ real _ escape_string而不是PHP3 mysql_escape_string。
  • 第一个函数应该被称为html或其他东西。 userinput听起来含糊不清,歪曲。
  • HTML转义需要更多参数htmlspecialchars($str, ENT_QUOTES, "UTF-8")才能完全安全
  • 将危险的SQL关键字列入黑名单并不是一个好主意。它提示使用SQL查询的错误方法(如果您通过HTTP请求接收查询,那就是您的问题)。
    • 此外,您不应尝试过滤它们。而是检测到它们,立即写入错误/安全日志和die()。如果试图规避安全性,那么尝试任何“清理”请求是没有意义的。

答案 2 :(得分:2)

您还可以使用与PHP捆绑在一起的filter_*函数,并为您提供根据特定过滤规则过滤请求参数的机制。

使用few extra tricks,您甚至可以过滤不同类型数据的数组(感谢erisco!)。

class sanitizer {

  public function sanitizeValues($values, $filters) {

    $defaultOptions=FILTER_FLAG_NO_ENCODE_QUOTES | FILTER_FLAG_STRIP_LOW | FILTER_NULL_ON_FAILURE;

    $filters=(array)$filters;
    $values=(array)$values;
    foreach ($filters as $key => $filter) {
        if($parts=explode('/', $key)){
            $v=&$values;
            foreach ($parts as $part){
                $v=&$v[$part];
            }
            $filter=(array)$filter;
            $filter[1]=isset($filter[1])?$filter[1]:$defaultOptions;
            $v=filter_var($v, $filter[0], $filter[1]);
            // consider if you really need this here instead of PDO
            // $v=mysql_real_escape_string($v); 
        }
        else{
            $values[$key]=isset($values[$key]) ? filter_var($values[$key], $filter[0], $filter[1]) : null;
        }

    }
    return $values;
  }
}

$manager=sanitizer::sanitizeValues($_GET['manager'], array(
                 'manager/managerID'=>FILTER_VALIDATE_INT,           
                 'manager/username'=>FILTER_SANITIZE_STRING,
                 'manager/name'=>FILTER_SANITIZE_STRING,
                 'manager/email'=>FILTER_SANITIZE_STRING,
                 'manager/phone'=>FILTER_SANITIZE_STRING,
                 'manager/bio'=>FILTER_SANITIZE_STRING,
                 'manager/enabled'=>FILTER_VALIDATE_BOOLEAN,
                 'manager/password'=>FILTER_SANITIZE_STRING));

这将根据_GET中的'manager'参数生成一个包含所有必需字段的数组,所有值都已过滤,并且可选地进行转义。