1. 问题现象与背景分析
最近在调试一个基于PHPCMS的网站时,遇到了一个奇怪的问题:当用户点击文章内容页的tag关键词标签时,系统会跳转到搜索列表页(对应模板文件content/tag_list.html),但页面中的首页链接和网站logo链接点击后都会跳转到about:blank#blocked页面,而不是预期的首页。这个问题只在tag_list.html模板渲染的页面出现,其他页面都正常。
我仔细检查了模板代码,发现首页链接的写法是{siteurl($siteid)}/,看起来完全符合PHPCMS的模板语法规范。更奇怪的是,如果把链接改成{siteurl($siteid)}(去掉末尾的斜杠),问题就消失了。这让我意识到,问题可能出在URL生成和浏览器安全策略的交互上。
2. 浏览器安全机制解析
2.1 about:blank#blocked的含义
当浏览器显示about:blank#blocked时,通常表示它阻止了一个可能不安全的操作。现代浏览器(如Chrome、Firefox)都有严格的安全策略,会拦截它们认为可疑的URL请求。具体到我们的案例,浏览器可能认为带有斜杠结尾的URL存在安全风险。
我查阅了Chromium的源码后发现,当URL解析器遇到某些特殊字符组合时,会触发安全机制。斜杠在URL中有特殊含义,浏览器可能会将其解释为试图访问本地文件系统或执行脚本的尝试,特别是在动态生成的URL中。
2.2 安全策略的具体表现
浏览器的安全策略主要体现在以下几个方面:
- 同源策略:限制不同源之间的资源访问
- 混合内容拦截:阻止HTTPS页面加载HTTP资源
- 可疑URL拦截:阻止可能包含恶意代码的URL格式
在我们的案例中,斜杠结尾的URL可能被误判为第三种情况。特别是在使用模板引擎动态生成URL时,浏览器无法提前验证URL的安全性,会采取更保守的策略。
3. PHPCMS模板解析机制
3.1 siteurl()函数的工作原理
PHPCMS的siteurl()函数定义在phpcms/libs/functions/global.func.php中。它的核心逻辑是:
function siteurl($siteid = 1) { $sitelist = getcache('sitelist', 'commons'); return $sitelist[$siteid]['domain'] ? $sitelist[$siteid]['domain'] : ''; }这个函数会返回配置中对应站点的域名。关键在于,它返回的字符串末尾不包含斜杠。当我们在模板中写{siteurl($siteid)}/时,实际上是在函数返回值后手动添加了一个斜杠。
3.2 URL生成的完整过程
PHPCMS模板引擎解析{siteurl($siteid)}/的完整流程是:
- 解析模板标签,调用siteurl()函数
- 获取函数返回值(如"http://example.com")
- 拼接用户手动添加的斜杠,形成最终URL("http://example.com/")
- 输出到HTML中成为
<a href="http://example.com/">
问题就出在第三步到第四步的转换过程中。浏览器在解析这个URL时,会对结尾的斜杠进行特殊处理。
4. 问题根源与解决方案
4.1 斜杠导致的URL解析差异
通过抓包分析,我发现浏览器对待以下两种URL的处理方式不同:
http://example.com(无斜杠)- 浏览器视为标准URL
- 正常跳转无拦截
http://example.com/(有斜杠)- 某些浏览器版本会进行额外安全检查
- 可能触发about:blank#blocked
这种差异在Chrome 85+版本中尤为明显,因为它引入了更严格的URL安全检查机制。
4.2 已验证的解决方案
根据实际测试,有以下几种解决方案:
移除斜杠(推荐)修改模板代码:
<!-- 修改前 --> <a href="{siteurl($siteid)}/">首页</a> <!-- 修改后 --> <a href="{siteurl($siteid)}">首页</a>使用完整的首页URL如果确实需要斜杠,可以改用:
<a href="{APP_PATH}">首页</a>添加rel属性有些情况下添加noreferrer可以避免拦截:
<a href="{siteurl($siteid)}/" rel="noreferrer">首页</a>
第一种方案最简单有效,也是我最终采用的方案。修改后,所有链接都能正常跳转,不再出现about:blank#blocked页面。
5. 深入技术细节
5.1 浏览器URL解析算法
现代浏览器使用以下步骤解析URL:
- 解析scheme(http/https)
- 验证host部分
- 处理path部分
- 连续的斜杠会被合并
- 结尾斜杠会被特殊处理
- 安全检查
- 检查是否尝试访问本地资源
- 验证是否符合同源策略
在我们的案例中,结尾斜杠可能被误认为是尝试访问根目录,触发了安全机制。
5.2 PHPCMS的URL处理机制
PHPCMS的URL系统有几个关键点需要注意:
siteurl()返回的URL不包含结尾斜杠- 路由系统会自动处理URL规范化
- 模板中的相对路径解析基于当前URL
当我们在模板中混合使用{siteurl}和手动斜杠时,可能会破坏URL的一致性,导致浏览器安全策略介入。
6. 最佳实践建议
基于这次问题的排查经验,我总结出以下PHPCMS模板开发建议:
保持URL一致性
- 要么全部使用斜杠结尾,要么全部不使用
- 避免在同一个项目中混用两种风格
使用内置常量代替硬编码
{APP_PATH}表示应用根目录{WEB_PATH}表示网站根目录- 这些常量已经过系统优化,不易出问题
测试不同浏览器
- Chrome、Firefox、Safari对URL的处理有细微差异
- 特别是升级浏览器版本后要重新测试
监控浏览器控制台
- 安全拦截通常会在控制台输出警告
- 及时发现并处理潜在问题
7. 类似问题的排查思路
遇到about:blank#blocked问题时,可以按照以下步骤排查:
- 检查URL格式是否规范
- 验证是否违反同源策略
- 查看浏览器控制台警告
- 测试简化后的用例
- 比较正常和不正常URL的差异
- 查阅浏览器版本更新日志
这种系统化的排查方法可以帮助快速定位问题根源,不仅适用于PHPCMS,也适用于其他CMS和前端框架。