php 防止sql注入

Q:如果把用户输入的没有任何改动的放到SQL的查询语句中,很有可能会导致SQL注入,比如说下面的例子:

$unsafe_variable = $_POST['user_input']; 

mysql_query("INSERT INTO `table` (`column`) VALUES ('$unsafe_variable')");

为什么会有注入漏洞呢?因为用户可以输入value'); DROP TABLE table;-- 然后查询语句就变成了这样

INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')

 

A:通过使用预编译语句(prepared statements)和参数化查询(parameterized queries)。

有两种方式去完成这个:

1. 使用PDO对象(对于任何数据库驱动都好用)
$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');

$stmt->execute(array('name' => $name));
2. 使用MySqli
$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
$stmt->bind_param('s', $name);
$stmt->execute(); 

================

通常有一下几种方法:

(1)输入验证和过滤
(2)预处理Sql语句
(3)采用存储过程
(4)输入白名单
(5)一般的简单过滤,直接用php的addslashes函数即可。

全面防注入:

function inject_check($sql_str) {
 return eregi('select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile', $sql_str);  // 进行过滤
}
function verify_id($id=null) {
 if (!$id) { exit('没有提交参数!'); }  // 是否为空判断
 elseif (inject_check($id)) { exit('提交的参数非法!'); }  // 注射判断
 elseif (!is_numeric($id)) { exit('提交的参数非法!'); }  // 数字判断
 $id = intval($id);  // 整型化
 return $id;
}

function str_check( $str ) { if (!get_magic_quotes_gpc()) { // 判断magic_quotes_gpc是否打开 $str = addslashes($str); // 进行过滤 } $str = str_replace("_", "\_", $str); // 把 '_'过滤掉 $str = str_replace("%", "\%", $str); // 把 '%'过滤掉 return $str; }

function post_check($post) { if (!get_magic_quotes_gpc()) { // 判断magic_quotes_gpc是否为打开 $post = addslashes($post); // 进行magic_quotes_gpc没有打开的情况对提交数据的过滤 } $post = str_replace("_", "\_", $post); // 把 '_'过滤掉 $post = str_replace("%", "\%", $post); // 把 '%'过滤掉 $post = nl2br($post); // 回车转换 $post = htmlspecialchars($post); // html标记转换 return $post; }

 

    /**
     * 转义需要插入或者更新的字段值
     *
     * 在所有查询和更新的字段变量都需要调用此方法处理数据
     *
     * @param mixed $str 需要处理的变量
     * @return mixed 返回转义后的结果
     */
    public function escape($str) {
        if (is_array($str)) {
            foreach ($str as $key => $value) {
                $str[$key] = $this->escape($value);
            }
        } else {
            return addslashes($str);
        }
        return $str;
    }

使用实例:

public function _saveWithWhere($tableName, $row, $where, $sync = false) {
        // 生成要插入/更新的字段的SQL字符串
        $values = '';
        foreach ($row as $searchKey => $val) {
            $values .= "`{$searchKey}` = '{escape($val)}',";
        }
        $values = trim($values, ",");

        // 有itemId的话就UPDATE没有的话就INSERT
        if (trim($where)) {
            $sql = "UPDATE {$tableName} SET {$values} WHERE {$where} ";
        }else {
            $sql = "INSERT INTO {$tableName} SET {$values}";
        }
          $this->saveLog($sql);
        // lib_DB->update 只返回  boolean 当 insert 的时候需要获取 last_id 就不行
        return $this->_update($sql, $sync);
    }

其他重要:

1. http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php

 

posted on 2016-10-08 21:53  星空守望者--jkmiao  阅读(157)  评论(0编辑  收藏  举报