我想使用像$ GET [name]这样的变量,它始终输出一个MySQL安全版本的$ _GET [name],即使$ GET [name]的值在脚本中某处发生了变化。
所以:
$_GET[name] = "Timmy O'Toole";
echo $GET[name]; // Timmy O\'Toole
$_GET[name] = "Tommy O'Toole";
echo $GET[name]; // Tommy O\'Toole
这可行吗?如果没有,你能想到任何其他可能不起作用的方式吗? (我希望能够在字符串中使用变量并让它们自动进行评估,而不必进行大量的连接。)
更新
我使用了马里奥解决方案的一个版本,它似乎有效:
// Assume $_REQUEST['name'] = "Timmy O'Toole";
class request_safe_vars IMPLEMENTS ArrayAccess {
var $array = array();
function offsetGet($varname) {
return mysql_real_escape_string($_REQUEST[$varname]);
}
function offsetSet($name, $value) { }
function offsetUnset($name) { }
function offsetExists($name) { }
}
$REQUEST = new request_safe_vars();
$_REQUEST['name'] = $_REQUEST['name'].' MODIFIED';
$query = "SELECT id FROM user WHERE name = '{$REQUEST['name']}'";
// Query output:
// SELECT id FROM user WHERE name = 'Timmy O\'Toole MODIFIED'
答案 0 :(得分:3)
你不想这样做。
相反,你要做的事情 - 确保数据库只获得正确的值 - 是正确的,但你采用的方式是一种糟糕的方法。
通过选择具有此功能的数据库适配器(<{3}}这样的数据库适配器,您应该在使用时转义所有输入,而不是在使用它时 。 。 PDO使用预准备语句和PDO is a great example 自动转义和引用输入。以下是parameter binding:
的示例$statement = $pdo->prepare('SELECT id FROM users WHERE name = ?');
$statement->execute(array( $_GET['name'] ));
if($statement->rowCount() > 0) {
echo "I found you!";
} else {
echo "You don't exist. :(";
}
带有占位符和绑定的预处理语句是确保SQL免受攻击的最明智和最安全的方法。
答案 1 :(得分:1)
这对于实现ArrayAccess的对象是可行的。通过将$ GET转换为对象,您可以使用魔术offsetSet
和offsetGet
方法来实现此目的。
class safe_vars IMPLEMENTS ArrayAccess {
var $array = array();
function offsetGet($varname) {
return mysql_real_escape_string($this->array[$varname]);
}
function offsetSet($name, $value) {
$this->array[$name] = $value;
}
function offsetUnset($name) { }
function offsetExists($name) { }
}
这就是你如何使用它:
$GET = new safe_vars();
$GET["name"] = "Timmy O'Toole";
echo $GET["name"]; // Timmy O\'Toole
我实际上有一些类似的东西(但从未实现set
部分),它专门适用于$_GET
(如您的问题中所列)。 http://sourceforge.net/p/php7framework/svn/60/tree/trunk/php7/input.php?force=True - 例如,可以将其配置为默认应用sql
过滤器。虽然这种方法有点像magic_quotes,即使它使用了正确的转义函数。
答案 2 :(得分:0)
首先,在'name'周围加上引号,除非你故意将它定义为常量。
另一个建议是使用DB包装器类,如PDO,mysqli或您自己的,并使用预准备语句并为您转义输入。这有利于在最后可能的时间转义数据,这是最佳的。或者你可以创建一个非常简单的包装函数,例如
function get($key) {
return isset($_GET[$key]) : mysql_real_escape_string($_GET[$key]) : null;
}
定义一个类(除非你只是静态使用它)的问题是它剥离了它的超全局状态$_GET
并且你被迫使用全局(邪恶)或将所有get参数传递给本地闭包。