使用 preg_match 时是否需要转义字符串?
Do I need to escape a string when using preg_match?
我正在使用一个简单的 HTML 网络表单来收集用户名和密码。我使用 preg_match
只允许 A-Z,0-9 个字符用于用户名。我在下面使用以下代码:
if (preg_match('/[^A-Za-z0-9]/', $_POST["username"])) {
echo '<script>alert("Usernames can only contain A-Z, 0-9")</script>';
}
我需要使用 mysqli_real_escape_string
来转义这个字符串吗?如果是这样,它仍然适用于所有情况吗?如果不是,我将面临哪些安全风险,我该如何预防?
(我在将用户名放入我的查询和数据库之前对其进行了转义)
你永远不应该使用 mysqli_real_escape_string
。只是忘记这个功能甚至存在。
如果您将 PHP 变量放入 SQL 中,那么即使您将它们转义,您也没有正确执行此操作。您必须使用参数绑定并且不要以任何方式修改输入,除非您的业务逻辑需要它。
为了防止 SQL 注入(我假设这是您的目标),您必须使用占位符和参数绑定。在 mysqli 中它看起来像这样:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'user', 'pass', 'db');
$mysqli->set_charset('utf8mb4'); // always set the charset
$username = $_POST["username"];
$password = password_hash($_POST["password"], PASSWORD_DEFAULT);
$stmt = $mysqli->prepare('INSERT INTO users(username, passwordHash) VALUES(?,?)');
$stmt->bind_param('ss', $username, $password);
$stmt->execute();
我建议从 mysqli 切换到 PDO。它提供更多并且更易于使用。在 PDO 中,相同的示例如下所示:
$dsn = "mysql:host=localhost;dbname=db;charset=utf8mb4";
$pdo = new PDO($dsn, $user, $pass, [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_EMULATE_PREPARES => false
]);
$username = $_POST["username"];
$password = password_hash($_POST["password"], PASSWORD_DEFAULT);
$stmt = $pdo->prepare('INSERT INTO users(username, passwordHash) VALUES(?,?)');
$stmt->execute([$username, $password]);
我正在使用一个简单的 HTML 网络表单来收集用户名和密码。我使用 preg_match
只允许 A-Z,0-9 个字符用于用户名。我在下面使用以下代码:
if (preg_match('/[^A-Za-z0-9]/', $_POST["username"])) {
echo '<script>alert("Usernames can only contain A-Z, 0-9")</script>';
}
我需要使用 mysqli_real_escape_string
来转义这个字符串吗?如果是这样,它仍然适用于所有情况吗?如果不是,我将面临哪些安全风险,我该如何预防?
(我在将用户名放入我的查询和数据库之前对其进行了转义)
你永远不应该使用 mysqli_real_escape_string
。只是忘记这个功能甚至存在。
如果您将 PHP 变量放入 SQL 中,那么即使您将它们转义,您也没有正确执行此操作。您必须使用参数绑定并且不要以任何方式修改输入,除非您的业务逻辑需要它。
为了防止 SQL 注入(我假设这是您的目标),您必须使用占位符和参数绑定。在 mysqli 中它看起来像这样:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'user', 'pass', 'db');
$mysqli->set_charset('utf8mb4'); // always set the charset
$username = $_POST["username"];
$password = password_hash($_POST["password"], PASSWORD_DEFAULT);
$stmt = $mysqli->prepare('INSERT INTO users(username, passwordHash) VALUES(?,?)');
$stmt->bind_param('ss', $username, $password);
$stmt->execute();
我建议从 mysqli 切换到 PDO。它提供更多并且更易于使用。在 PDO 中,相同的示例如下所示:
$dsn = "mysql:host=localhost;dbname=db;charset=utf8mb4";
$pdo = new PDO($dsn, $user, $pass, [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_EMULATE_PREPARES => false
]);
$username = $_POST["username"];
$password = password_hash($_POST["password"], PASSWORD_DEFAULT);
$stmt = $pdo->prepare('INSERT INTO users(username, passwordHash) VALUES(?,?)');
$stmt->execute([$username, $password]);