在内容型网站里,文章正文经常会引用外部资料、工具页面或参考链接。最简单的做法是让外链直接出现在正文 HTML 里,但这样会带来几个问题:源代码会直接暴露站外 URL,用户离站前缺少明确提示,中转页也可能被他人滥用成公共开放跳转器。本次优化的目标,就是把外链访问从“直接流出”改成“本站可控的中转流程”。

外部链接跳转中转页怎么设计?一次从直出外链到安全中转的优化复盘

为什么不只做前端点击拦截

最初很容易想到用 JavaScript 监听正文链接点击,然后临时跳转到中转页。这种方式交互上能工作,但并不能真正解决“链接直接流出”的问题。因为页面源代码里仍然保留着原始站外 URL,搜索引擎、采集器或禁用 JavaScript 的环境依然可以直接看到这些链接。

因此更稳妥的方案是把处理前移到模板渲染阶段:正文在输出 HTML 时,就把站外链接改写成本站中转地址。这样用户看到的页面、爬虫抓到的源代码,以及浏览器实际点击的 href,都是统一的中转链接。

整体设计思路

这次方案分成两部分:第一部分是模板层的外链改写逻辑,负责识别正文中的站外链接,并生成中转地址;第二部分是中转页本身,负责校验访问来源、展示风险提示、控制倒计时,并在用户确认后跳转到目标网站。

在模板层,只处理正文区域中的 http 和 https 链接。站内链接、锚点链接、邮件、电话、脚本协议等都不会被改写。对真正的站外链接,会生成类似“中转页 + 编码后的目标地址 + 签名”的结构。这里的签名只用于说明设计方法,实际密钥不应写进公开文章,也不应使用示例值上线。

中转页需要解决的安全问题

一个外链中转页如果只接收一个 url 参数并跳转,很容易变成开放跳转器。别人可以把你的域名包装成任意外部地址,用在垃圾链接、钓鱼跳转或误导用户的场景里。为了降低这种风险,中转页需要同时做多层校验。

第一层是 Referer 来源限制。中转页只允许从本站文章页进入,直接从外部网站构造请求访问时会被拒绝。第二层是签名校验。模板生成中转链接时使用服务端约定的密钥对目标参数签名,中转页收到请求后再验证签名是否匹配。这样即使别人知道中转页参数格式,也无法随便构造新的跳转目标。

第三层是目标地址校验。中转页只允许 http 和 https 协议,拒绝内网地址、本机地址、异常长度 URL、带用户名密码的混淆 URL,以及不符合解析规则的地址。这样可以避免中转页被当作探测内网、隐藏真实目标或制造混淆链接的工具。

交互体验怎么设计

安全提示页不应该只是一句“正在跳转”。用户至少需要知道自己即将访问哪个域名、是否还在本站、是否存在非加密连接风险。因此中转页展示目标域名、完整目标地址、倒计时进度、立即前往、暂停倒计时和返回首页几个基础操作。

对于普通 HTTPS 外部链接,可以默认给出几秒倒计时,并允许用户暂停。对于 HTTP 非加密链接,则不建议自动跳转,而是改为手动确认。这样既不会打断正常阅读,也给高风险目标留出一个明显的确认步骤。

外部链接跳转中转页怎么设计?一次从直出外链到安全中转的优化复盘

离站时的来源保护

还有一个容易忽略的细节:文章页进入中转页时,需要保留本站 Referer,因为中转页要用它判断请求是否来自本站。但中转页真正跳到第三方网站时,就不应该继续把本站页面作为 Referer 传出去。因此中转页可以设置 Referrer-Policy,让最终离站访问不再携带本站来源。

这也是为什么正文中的中转链接不应添加 noreferrer,否则浏览器进入中转页时就不会带 Referer,来源校验会把自己的正常访问也拦掉。正确做法是:文章页到中转页保留 Referer,中转页到外站再阻断 Referer。

上线前的注意事项

真正部署时,签名密钥必须使用随机生成的强密钥,并且只保存在服务端代码或配置中,不要写进文章、前端脚本或公开仓库。模板改写逻辑和中转页校验逻辑使用的密钥必须保持一致,否则所有中转链接都会校验失败。

发布后还需要清理模板缓存,检查文章源代码中的外链是否已经变成中转地址,并分别测试正常站内来源、无 Referer、伪造参数、HTTP 目标、HTTPS 目标等几类情况。只有这些路径都符合预期,外链中转才算真正闭环。

总结

外链中转页的核心不是“多一个跳转页面”,而是把外部访问变成一个可控流程:正文源代码不直接暴露站外 URL,中转页不被当成公共开放跳转器,用户离站前能看到目标和风险提示,最终跳出时也不继续传递本站来源。

这类设计适合内容站、工具导航、资料整理站和任何需要统一管理外链出口的网站。相比单纯的前端点击拦截,模板渲染阶段改写加服务端校验,才更接近可维护、可审计、可长期使用的方案。