第 5 章 · Web 开发 · 第 5.1 课
PHP 怎么处理网页请求
到目前为止我们都在写“普通程序”。PHP 真正的主场是网站:
- 浏览器请求
https://example.com/hello.php?name=Tom; - Web 服务器(Nginx、Caddy 等)把请求交给 PHP;
- PHP 执行
hello.php,把请求里的数据放进几个超全局变量; - 脚本 echo 出来的内容就是返回给浏览器的网页。
| 变量 | 里面装的是 |
|---|---|
$_GET | 网址 ? 后面的参数 |
$_POST | 表单用 POST 提交的数据 |
$_SERVER | 请求方法、路径、IP 等信息 |
$_COOKIE | 浏览器带来的 cookie |
$_SESSION | 服务器端为这个访客保存的会话数据 |
练功房里没有真实的网络请求,所以下面的例子会先手动给 $_GET 赋值来模拟一次请求。
永远不要相信用户输入:XSS
用户输入的内容如果原样输出到网页里,攻击者就能塞进一段 <script>,在别人的浏览器里执行,偷走登录状态。这叫 XSS(跨站脚本攻击)。
防御方法很简单:输出到 HTML 之前一律用 htmlspecialchars() 转义,它会把 <、>、"、'、& 变成无害的 HTML 实体。运行下面的代码,再切到“网页预览”对比一下。
表单和校验
HTML 表单用 method="post" 提交时,数据会出现在 $_POST 里。服务器端必须再校验一遍(浏览器端的校验可以被绕过)。filter_var 能校验邮箱、整数、网址等常见格式。
Session:记住“你是谁”
HTTP 请求之间互相不认识。要实现“登录后一直保持登录”,PHP 用 session:session_start() 之后,往 $_SESSION 里存的东西会保存在服务器上,浏览器只拿到一个随机的会话 id(存在 cookie 里),下次请求带回来,PHP 就能找到对应的数据。
这个网站的注册登录就是这么做的。session 需要真实的浏览器请求,练功房里没法演示,看一下写法即可:
<?php
// login.php:密码校验通过后
session_start();
session_regenerate_id(true); // 换一个新的会话 id,防止会话固定攻击
$_SESSION['user_id'] = 42;
// 其他页面
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: /login.php');
exit;
}
echo "欢迎回来,用户 " . $_SESSION['user_id'];选择题
把用户输入的内容输出到网页之前,为什么要用 htmlspecialchars?
练习 1
分页参数
已通过列表页每页显示 10 条,页码来自 $_GET['page']。算出这一页显示的是第几条到第几条,输出格式:
显示第 21 到 30 条要考虑用户乱传的情况:没有 page 参数、page 是 0、负数或者不是数字时,都按第 1 页处理。检查时会换几种请求来测。
练习 2
转义函数
已通过很多项目会写一个短名字的转义函数,模板里用起来方便。写函数 e(string $s): string,返回转义后的字符串,单引号和双引号都要转义。
e('<b>')→<b>e('"x"')→"x"e("It's")→It's