历时两天,终于解决了ThinkPHP5框架接入腾讯云TEO无法登录后台的问题。
温馨提示:这篇文章已超过34天没有更新,请注意相关的内容是否还可用!
好久没有写教程文章了,不是别的仅仅是因为AI爆火之后没有什么值得记录的,这不今儿就来了,起因有一个TP5框架项目需要引入CDN,在综合选择之后部署了腾讯云的TEO,也就是边缘加速,一切部署之后就下班了,结果昨天甲方告知后台系统无法登录,我想着小意思哈,肯定是缓存问题,我把缓存设置下就行了,结果还真不是我以为我以为的就是我以为的!!!

先说下结论
腾讯云 TEO(EdgeOne)免费版会在回给浏览器的响应中剥离 Set-Cookie(workbuddy说的,不是我说的),依赖「服务端 Session + PHPSESSID Cookie」的 ThinkPHP 5.1 后台因此无法维持登录、陷入登录循环。
修复办法是用 TEO 边缘函数在边缘节点把源站的 Set-Cookie 重新下发,不需要修改服务器的源代码。
一、环境
框架:ThinkPHP 5.1 LTS
运行:Nginx 1.24 + PHP 7.4 + MySQL 8.0
接入:域名
www.itlaoli.com走 TEO 加速(回源 443、强制 HTTPS、HSTS/2)后台:模块
admin,登录链路Login/checkLogin→ 写session('admin',...)→ JS 跳转Index/index→Common::initialize()校验 session
二、现象
登录页能打开,输入账号密码点登录,提示成功却又跳回登录页,无限循环。使用服务器IP解析其他域名访问正常,走 TEO 不行。
三、排查时间线(部分关键节点)
先怀疑 HTTPS 识别
isSsl()失败 → 源站自己监听 443,排除。看请求头
PHPSESSID一致 → 排除「浏览器 cookie 没带上」。怀疑 session 没落盘 →
php -i发现走 Redis,且sess_test.php证明 Redis 能写,排除。看
checkLogin响应头没有 Set-Cookie → 方向转向「响应侧 cookie 没种下」。加
Session::close()、改 NginxCache-Control: private、独立location全 404、server 级if语法错 → 均无效。直连
htgl登录成功(日志fr89...一路到welcome),www全PHPSESSID=空→ 实锤 TEO 剥离 Set-Cookie。查官方文档 1552/84080「设置 Cookie」→ 锁定边缘函数方案。
部署边缘函数时踩进两个新坑:
onRequest入口报错、Content-Encoding冲突空白页 → 修正后成功。
四、根因
TEO 免费版「修改 HTTP 节点响应头」能力仅有 设置/删除/增加,没有「保留/透传」,对 Set-Cookie 默认剥离。浏览器永远拿不到 PHPSESSID,每次请求都是新会话,登录即失效。
而且按照workbuddy的说法了,不能设置增加,只能设置透传/保留,但是TEO没有,至少免费版没有,收费版我用过不晓得哈。
解决方案(最终可用代码)
TEO 规则触发的边缘函数(匹配 /admin/*):
async function handleRequest(request) {
// 回源获取响应
const response = await fetch(request);
// 读取源站 Set-Cookie
const setCookie = response.headers.get('set-cookie');
if (!setCookie) {
return response;
}
// 复制头,补 Set-Cookie
const newHeaders = new Headers(response.headers);
newHeaders.set('Set-Cookie', setCookie);
// 关键:删除 Content-Encoding / Content-Length,避免 body 与编码声明不一致
newHeaders.delete('Content-Encoding');
newHeaders.delete('Content-Length');
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: newHeaders
});
}
addEventListener('fetch', (event) => {
event.respondWith(handleRequest(event.request));
});原理:边缘函数从源站响应读取 Set-Cookie,在「TEO 剥离」之前重新下发,浏览器正常拿到 PHPSESSID,session 得以维持。
后续增加了@301重定向www,因为边缘函数接管了/admin/*,所以服务器设置的重定向失效,导致没有www的网站提示账号密码错误,所以我新增了重定向,有需要的自己添加。
触发规则:
匹配类型选择【URL path】,运算符设置【等于】,值设置【/admin/*】(根据项目后台的实际目录设置,图片为演示站)

踩坑点(文章重点)
首先我使用了很多AI软件,包括不限于Qoderwork、TRAE Work,千问、文心一言,在最后放弃的一瞬间,先说为什么放弃,因为真的没有办法实现了,只能暂时用其他域名绑定项目,然后解析服务器IP来访问后台(兜底方案)。我真的是不了解TP5框架,说什么session我也听不懂,可以说小白刚刚解除电脑那个级别吧,然后我就像既然是session有问题,去官网搜一下关键词试试,当时呢我也看不懂,毕竟文档都是留给大佬看的,所以我就把最后的稻草放在了workbuddy(不是说只要它才能解决问题哈)里,然后经过三轮调试,终于在无痕模式下成功登入,但是能感觉到有一丢丢的延迟,可能是传输set-session或者其他原因吧。无论怎样算是成功了。聊聊跟AI总结的几个采坑点,自己记录。
别看错请求:
Set-Cookie只在「建立会话那一次」出现(登录页首次加载的 GET 响应头),不是checkLoginPOST。在 POST 上看到「只有 Cookie、没有 Set-Cookie」是正常的,别被误导。先区分请求侧还是响应侧:F12 看
checkLogin响应头有没有Set-Cookie,一眼定位是「cookie 没带上」还是「cookie 没种下」。别乱猜 HTTPS:源站自身监听 443 时
isSsl()正常,问题未必在 HTTPS。session 驱动看 php.ini:TP5
config/session.php里type => ''时,session 由 php.ini 的save_handler决定(本例是 phpredis,不是文件),排查别被路径误导。Nginx 独立 location 会 404:
location ~ ^/admin/ { add_header ... }优先级高于 PHP 处理器且无 fastcgi,会把后台打 404。要加响应头必须放进enable-php-74.conf的 PHP location 内。是的你没看错,我都已经开始修改nginx规则了,但是无效,属于无用功。Cache-Control: private 救不了:TEO 对 Set-Cookie 是硬剥离,
Cache-Control出现 ≠ 成功,判定标准始终是Set-Cookie是否在响应头出现。通过TEO规则引擎配置了Cache-Control头,但即便显示也是无用,原因不在这。边缘函数入口别用错:TEO 规则触发的边缘函数用
addEventListener('fetch', ...)(文档 1552/84080);onRequest(context)是 EdgeOne Pages/Makers 的写法,用错会Error return from script。Content-Encoding 冲突:重建
Response时若保留Content-Encoding: gzip但 body 已被运行时解压,浏览器会ERR_CONTENT_DECODING_FAILED白屏。必须delete('Content-Encoding')和delete('Content-Length')。免费版能力受限:「修改 HTTP 节点响应头」只有设置/删除/增加,无法透传;后台这类动态鉴权路径,要么直连源站,要么上边缘函数。
最后
我这两天的折腾到如今也还是不理解,为什么像WordPress和zblog可以直接配置TEO而没有问题,为什么TP框架进寸步难行呢?可能就是因为不了解这个程序,毕竟这样两天的时间需要记录下问题以及解决办法,但是我感觉这个不是问题的根本虽然现在能登陆了,可是为什么会有一丢丢的延迟,这个在服务器直接登录是察觉不到的,这就可能存在问题。我还去百度搜索了,也没有结论,难不成大家的TP框架都没有部署CDN么?还是说都是收费版没有任何问题呢?很费解,只能说自己的技术和经验还是少的可怜,除了zblog其他程序一概不知,惭愧惭愧~~~好了,大神有好的方案可以留言告诉我,静待佳音~~~



还没有评论,来说两句吧...