PHP的HTTP请求方法:GET与POST详解
GET方法基础使用
GET是HTTP协议中最常用的请求方法之一,主要用于从服务器获取数据。作为HTTP/1.1标准定义的8种请求方法(RFC 7231)之一,GET方法的特点是只请求数据而不修改服务器资源。在PHP中,GET方法传递的数据会附加在URL后面,形成查询字符串(Query String),这种设计使得GET请求具有以下特性:
- 缓存机制:GET请求可以被浏览器缓存,提高重复访问时的加载速度
- 可收藏性:完整的URL可以被收藏为书签,包括所有查询参数
- 历史记录:请求会保存在浏览器历史记录中,用户可通过后退按钮返回
- SEO友好:可以被搜索引擎爬虫索引,有利于内容被发现
- 可分享性:包含完整参数的URL可以被轻松分享和传播
GET请求的URL结构通常遵循以下模式:
协议://域名/路径?参数1=值1&参数2=值2
例如一个典型的商品搜索URL:
https://www.example.com/search?keyword=laptop&category=electronics&sort=price&page=2
GET数据接收示例
测试网址示例
基础URL:
http://127.0.0.1/1.php
带GET参数的URL:
http://127.0.0.1/1.php?a=1&b=2
在这个例子中:
- 我们向1.php文件传递了2个参数:a和b
- a和b称为"键名"(key),是参数标识符
- 1和2分别是a和b的"键值"(value),是参数的具体数据
- 问号(?)标志着URL路径的结束和查询字符串的开始
- 与号(&)用于分隔不同的参数键值对
- 参数会自动被URL编码(如空格变为%20)
PHP接收GET参数代码
<?php
// 从$_GET超全局数组中获取参数值
$a = isset($_GET['a']) ? $_GET['a'] : 0; // 获取键名为a的值,结果是1,设置默认值0
$b = isset($_GET['b']) ? $_GET['b'] : 0; // 获取键名为b的值,结果是2,设置默认值0
// 对获取的值进行类型转换和验证
$a = is_numeric($a) ? (int)$a : 0;
$b = is_numeric($b) ? (int)$b : 0;
// 对获取的值进行加法运算
$c = $a + $b;
// 安全输出结果
echo htmlspecialchars($c); // 输出结果3,防止XSS攻击
?>
GET参数格式详解
参数结构规范
- 键值对格式:每个参数采用严格的键名=键值形式
- 参数分隔:多个参数之间用&符号连接,形成参数链
- 引号处理:不需要为键值添加引号(字符串会自动处理)
- 特殊字符:需要进行URL编码(如空格编码为%20,/编码为%2F)
- 大小写敏感:参数名称区分大小写
- 顺序无关性:参数顺序通常不影响服务器处理
正确格式示例
标准URL:
http://example.com/page.php?name=John&age=25
带特殊字符的URL(编码后):
http://example.com/search.php?q=web%20development&sort=newest
带数组参数的URL:
http://example.com/filter.php?color[]=red&color[]=blue&size[]=M&size[]=XL
多层级参数:
http://api.example.com/data?filter[category]=books&filter[price][min]=10&filter[price][max]=50
错误格式示例
不需要加引号(错误):
http://example.com/page.php?name='John'&age='25'
参数分隔错误(错误):
http://example.com/page.php?name=John,age=25
缺少键名或键值(错误):
http://example.com/page.php?name=&age=25
未编码特殊字符(错误):
http://example.com/search.php?q=web development
GET方法的特点与应用场景
核心特点
可见性:
- 数据完全暴露在URL中,可以被书签保存
- 优点:便于分享和调试,用户可以看到请求的具体内容
- 缺点:不适合传输敏感信息,如密码、身份证号等
长度限制:
- 不同浏览器限制不同:
- IE: 2083字符
- Chrome: 8182字符
- Firefox: ~64KB
- Safari: ~80KB
- 服务器也可能有自己的限制(如Apache默认是8192字节)
缓存性:
- 可以被浏览器和代理服务器缓存
- 提高重复请求的响应速度
- 可以通过Cache-Control头控制缓存行为
幂等性:
- 多次执行相同GET请求不会改变服务器状态
- 适合数据查询操作
- 不适合数据修改操作
安全性:
- 仅适用于非敏感数据传输
- 会出现在浏览器历史记录中
- 会被服务器记录在访问日志中
- 可能被网络嗅探工具捕获
典型应用场景
搜索引擎查询:
https://www.google.com/search?q=php+tutorial&lang=en&start=10
分页显示:
http://example.com/news.php?page=2&items=10&sort=date_desc
筛选过滤:
http://example.com/products.php?category=electronics&price=100-200&sort=price_asc&in_stock=1
API数据获取:
http://api.example.com/users?id=123&fields=name,email,phone&expand=profile
网站分析跟踪:
http://example.com/page?utm_source=newsletter&utm_medium=email&utm_campaign=spring_sale
内容预加载:
http://example.com/article?preview=true&format=json
安全注意事项
敏感信息保护
永远不要通过GET方法传递以下信息:
- 密码
- 信用卡号
- API密钥
- 身份认证令牌
- 个人隐私信息
这些信息会出现在:
- 浏览器历史记录
- 服务器访问日志
- 代理服务器日志
- 第三方分析工具
- 引荐来源(Referer)头信息
输入验证
// 安全获取GET参数示例 - 整数处理
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
if($page < 1) $page = 1;
// 字符串参数过滤
$search = isset($_GET['q']) ? htmlspecialchars(trim($_GET['q']), ENT_QUOTES, 'UTF-8') : '';
// 数组参数处理
$colors = isset($_GET['colors']) ? (array)$_GET['colors'] : [];
$colors = array_map(function($color) {
return htmlspecialchars($color, ENT_QUOTES, 'UTF-8');
}, $colors);
// 邮箱验证
if (isset($_GET['email'])) {
$email = filter_var($_GET['email'], FILTER_VALIDATE_EMAIL);
if ($email === false) {
// 处理无效邮箱
}
}
SQL注入防护
// 使用PDO预处理语句防止SQL注入
$pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_GET['user_id']]);
$user = $stmt->fetch();
// 或者使用命名参数
$stmt = $pdo->prepare("SELECT * FROM products WHERE category = :category AND price > :min_price");
$stmt->execute([
':category' => $_GET['category'],
':min_price' => $_GET['min_price']
]);
$products = $stmt->fetchAll();
布尔值处理
对于布尔值参数,推荐使用以下格式:
数字形式:
http://example.com/api.php?active=1&verified=0
字符串形式:
http://example.com/api.php?active=true&verified=false
空参数形式:
http://example.com/api.php?active&no_verified
处理代码示例:
$active = isset($_GET['active']) ? filter_var($_GET['active'], FILTER_VALIDATE_BOOLEAN) : false;
$verified = isset($_GET['verified']) ? (bool)$_GET['verified'] : false;
CSRF防护
即使是GET请求,对于重要操作也应考虑CSRF令牌保护:
// 生成CSRF令牌
session_start();
$token = bin2hex(random_bytes(32));
$_SESSION['csrf_token'] = $token;
// 在GET请求中验证CSRF令牌
if (isset($_GET['action']) && $_GET['action'] === 'delete') {
if (!isset($_GET['csrf_token']) || $_GET['csrf_token'] !== $_SESSION['csrf_token']) {
header('HTTP/1.1 403 Forbidden');
die('CSRF token validation failed');
}
// 验证通过,执行删除操作
$id = (int)$_GET['id'];
// 执行删除逻辑...
// 使用后销毁令牌
unset($_SESSION['csrf_token']);
}
其他安全建议
请求方法限制:
- 敏感操作应限制只能通过POST请求
- 可以使用
$_SERVER['REQUEST_METHOD']检查请求方法
输出编码:
- 对所有输出到HTML的内容进行编码,防止XSS攻击
- 使用
htmlspecialchars()或模板引擎的自动转义功能
CORS策略:
- 设置适当的跨域资源共享策略
- 限制允许的来源、方法和头部
HTTPS加密:
- 始终使用HTTPS加密传输,防止中间人攻击
- 设置HSTS头强制使用HTTPS
速率限制:
- 对API端点实施速率限制,防止滥用