php收不到authorization头主因是cors预检失败导致请求未发出;需配置access-control-allow-headers: authorization,统一读取$_server['http_authorization']或'redirect_http_authorization',并在php中处理options请求并终止执行。

PHP 为什么收不到 Authorization 请求头
浏览器在跨域请求中发送 Authorization 头时,会先发一个 OPTIONS 预检请求。如果服务器没明确允许该头,预检就失败,后续请求根本不会发出——所以你根本看不到 Authorization,不是 PHP 没读到,是它压根没传过来。
常见现象:前端用 fetch 或 axios 带 Bearer xxx 发请求,后端 $_SERVER['HTTP_AUTHORIZATION'] 为空,getallheaders() 里也找不到 Authorization。
- 确保响应预检请求时包含
Access-Control-Allow-Headers: Authorization - 如果还用了自定义头(如
X-Request-ID),必须一并列在Access-Control-Allow-Headers里,不能用通配符*(除非不带凭据) - 若前端设置了
credentials: 'include',则Access-Control-Allow-Origin不能为*,必须写具体域名
PHP 中正确读取 Authorization 头的两种方式
Apache 服务器默认会剥离 Authorization 头,转成 REDIRECT_HTTP_AUTHORIZATION 放进 $_SERVER;而 Nginx 默认不剥离,但需配置 fastcgi_pass_request_headers on 才透传。所以不能只依赖 $_SERVER['HTTP_AUTHORIZATION']。
- 统一读法:优先检查
$_SERVER['HTTP_AUTHORIZATION'],不存在则 fallback 到$_SERVER['REDIRECT_HTTP_AUTHORIZATION'] - 更健壮的做法是用
getallheaders()(需 Apache + mod_php 或 PHP-FPM 配置支持),但它在某些 CGI 环境下不可用 - 示例提取逻辑:
$auth = $_SERVER['HTTP_AUTHORIZATION'] ?? $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ?? null; if ($auth && preg_match('/^Bearer\s+(.*)$/i', $auth, $matches)) { $token = $matches[1]; }
为什么 CORS 配置放在 .htaccess 里经常失效
很多 PHP 项目把 CORS 头直接写在 .htaccess 里,比如 Header set Access-Control-Allow-Origin "*",但这对预检请求(OPTIONS)无效——因为 .htaccess 的 Header 指令默认只作用于 2xx 响应,而 Apache 对 OPTIONS 预检常返回 200 但绕过常规 PHP 路由,导致头没生效。
立即学习“PHP免费学习笔记(深入)”;
- 解决方法:在 PHP 入口文件(如
index.php)开头手动输出 CORS 头,并显式处理OPTIONS请求 - 务必加
exit或die终止预检响应,避免后续业务逻辑执行 - 示例:
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { header('Access-Control-Allow-Origin: https://your-frontend.com'); header('Access-Control-Allow-Headers: Authorization, Content-Type'); header('Access-Control-Allow-Methods: GET, POST, OPTIONS'); header('Access-Control-Allow-Credentials: true'); exit; }
JWT token 解析后用户验证失败的隐藏原因
Authorization 头能取到了,token 也能解码,但验证用户时失败——这时候别急着查数据库逻辑,先确认时间戳和签发环境。
- 服务器时间不准会导致
exp/nbf校验失败,用date命令核对系统时间,或用ntpdate -q pool.ntp.org检查偏移 - 开发环境用
localhost,生产用域名,但 JWT 的iss(issuer)或aud(audience)字段硬编码了某一个,导致跨环境验证失败 - PHP 的
openssl_verify()对签名算法敏感,比如用RS256但公钥格式不对(PEM 缺 BEGIN/END 行,或含多余空格),会静默失败
跨域场景下,验证失败往往不是单一环节的问题,而是预检、头透传、时间同步、密钥加载四个点里任意一个断掉,整个链路就卡死。最容易被忽略的是服务器时间偏差和 OPTIONS 响应未终止执行。











