应先用isset()或空合并运算符判断键存在,再对用户名用filter_input(INPUT_POST, 'username', FILTER_SANITIZE_FULL_SPECIAL_CHARS)过滤,密码原样获取后交password_hash()处理。

PHP 用 $_POST 和 $_GET 接收表单数据,但直接读取不校验会出安全问题、乱码、空值崩溃——必须先判断存在性、过滤内容、转义输出。
怎么安全地从 $_POST 读取用户名和密码
用户提交登录表单后,$_POST['username'] 和 $_POST['password'] 不一定存在,也不可直接拼 SQL 或 echo 输出。
- 用
isset()或array_key_exists()判断键是否存在,避免 Notice 错误 - 用
filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING)过滤字符串(PHP 8.1+ 已弃用FILTER_SANITIZE_STRING,改用FILTER_SANITIZE_FULL_SPECIAL_CHARS或手动trim() + htmlspecialchars()) - 密码绝不做任何“过滤”,只用
isset($_POST['password']) ? $_POST['password'] : ''原样取值,后续交给password_hash()处理 - 示例:
$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_FULL_SPECIAL_CHARS) ?: ''; $password = $_POST['password'] ?? '';
为什么 $_GET 比 $_POST 更容易出乱码和 XSS
$_GET 数据来自 URL,天然暴露、长度受限、编码不可控;浏览器地址栏粘贴、分享链接时可能带非法字符或未编码空格/中文。
- URL 中的中文若未用
urlencode()编码,PHP 接收到的$_GET值可能是乱码(尤其在 Apache + mod_php 环境下) -
$_GET内容应默认视为“不可信输入”,哪怕只是分页参数?page=2,也要用filter_var($page, FILTER_VALIDATE_INT)校验 - 绝不能把
$_GET['q']直接插入 HTML:<h2>搜索结果:<?php echo $_GET['q']; ?></h2>—— 这是典型 XSS 入口 - 正确做法:
$q = htmlspecialchars($_GET['q'] ?? '', ENT_QUOTES, 'UTF-8'); echo "<h2>搜索结果:{$q}</h2>";
$_POST 和 $_GET 同名字段会互相覆盖吗
不会。PHP 中 $_POST 和 $_GET 是两个完全独立的超全局数组,同名键互不影响。但如果你用 $_REQUEST,它默认合并了 GET、POST、COOKIE(顺序由 request_order 配置决定),这就容易踩坑。
立即学习“PHP免费学习笔记(深入)”;
- 检查 php.ini 中
request_order = "GP"(默认),表示$_REQUEST优先取 GET,再取 POST;若设为"PG",则 POST 会覆盖 GET 同名项 - 强烈建议永远不用
$_REQUEST,显式写$_POST或$_GET,避免逻辑被配置悄悄改变 - 表单 method="get" 时,不要在 URL 上再手动拼
?id=123,否则$_GET会出现重复键(如两个id),PHP 只保留最后一个
真正麻烦的不是“怎么取值”,而是“取完之后怎么确保它没被篡改、没含恶意脚本、没破坏数据库查询”——每个 $_POST 或 $_GET 键都应该有明确的类型预期、过滤策略和上下文转义方式,少一步都可能让整个表单变成攻击入口。



















