无痕模式下裸域 HTTPS 整页无 CSS

一 现象

  • 无痕窗口打开 https://511yj.com:文字正常,整页没有 CSS 样式。
  • 无痕窗口打开 https://www.511yj.com:样式齐全。
  • 普通窗口看着「两个都正常」,是因为浏览器早先从 www 页面缓存过这些 CSS。
  • 站点启用了 Super Static Cache,首页由 C:\xampp\htdocs\super-static-cache\index.html.gz 提供,曾怀疑是解压后的 index.html 出了问题。

二 先把「解压坏了」排除掉

贴出来的首页源码里,所有样式表都是硬编码的 www 绝对地址:

<link rel='stylesheet' id='aldehyde-style-css' href='https://www.511yj.com/wp-content/themes/aldehyde/style.css?ver=1791971959' media='all' />
<link rel='stylesheet' id='aldehyde-bootstrap-style-css' href='https://www.511yj.com/wp-content/themes/aldehyde/assets/bootstrap/css/bootstrap.min.css?ver=1791953997' media='all' />
<link rel="canonical" href="https://www.511yj.com" />

没有相对路径、没有裸域地址。页面文字也正常渲染,不是 .gz 没解干净那种整页二进制乱码。解压这一步无罪。

三 逐层排除:一张被推翻的假设表

假设 验证命令 / 读数 结论
静态缓存按 Host 存了两份,裸域那份是旧的 dir /s /b C:\xampp\htdocs\*index.html.gz 只有一份 super-static-cache\index.html.gz,其余是 archives / guestbook / sitemap 等子页 否
裸域返回的 HTML 里 CSS 写成裸域或相对地址 两域分别 curl.exe -s --compressed https://511yj.com/ | findstr /i /c:"<link" 与 www 同命令,输出逐字一致,全是 www 绝对地址 否
裸域多一条 CSP 把 www 样式表判成跨源 curl.exe -sI ... | findstr /i /c:"content-security",两边都只有 upgrade-insecure-requests;,不限 style-src 否
CSS 文件本身被重写吞成 HTML curl.exe -sIL -o nul -w "code=%{http_code} type=%{content_type}\n" https://511yj.com/wp-content/themes/aldehyde/style.css,两域都 200 text/css 否
443 层没有把裸域规范化到 www 两域 curl.exe -sI https://.../ | findstr /i /c:"location" 都没有 Location 是,这是起点
WAF / 防盗链按 Referer 拦跨子域静态资源 带 Referer 对照(见下一节):裸域 Referer 拿到 text/html 5758 字节「网站防火墙」页,www Referer 拿到 text/css 8982 字节 是,实锤

四 实锤:带 Referer 的对照实验

关键动作是手动带上 Referer,模拟真实浏览器。在本地电脑 CMD 里跑(别在 ECS 上跑,原因见第七节):

curl.exe -s -o nul -w "ref=naked : code=%{http_code} type=%{content_type} size=%{size_download}\n" -H "Referer: https://511yj.com/" -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" "https://www.511yj.com/wp-content/themes/aldehyde/style.css?ver=1791971959"

curl.exe -s -o nul -w "ref=www   : code=%{http_code} type=%{content_type} size=%{size_download}\n" -H "Referer: https://www.511yj.com/" -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" "https://www.511yj.com/wp-content/themes/aldehyde/style.css?ver=1791971959"
Referer 读数 实际内容
https://511yj.com/ code=200 type=text/html size=5758 拦截页
https://www.511yj.com/ code=200 type=text/css size=8982 真正的样式表

把裸域那条返回体抓出来看:

curl.exe -s -H "Referer: https://511yj.com/" -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" "https://www.511yj.com/wp-content/themes/aldehyde/style.css?ver=1791971959" | findstr /i /c:"防火墙" /c:"<html" /c:"<!DOCTYPE"

返回的是 <!DOCTYPE html ...>、标题 网站防火墙、带 yunsuologo、正文写着「您的行为被识别为盗链,已被管理员 [www.511yj.com] 设置拦截」。FINDSTR: 写入错误 只是管道输出太长被中途断开,前面已经命中,不影响结论。

五 完整机制链

  1. 输入 https://511yj.com,443 的 vhost 不跳,Host 保持裸域。:80 那条 301 带 RewriteCond %{HTTPS} off,管不到 https。
  2. 返回共享的那份静态首页,里面 CSS 全部硬编码成 https://www.511yj.com/...。
  3. 浏览器带 Referer: https://511yj.com/ 向 www 请求样式表。
  4. 云锁「网站防火墙」防盗链判定为跨站盗链,回 5758 字节 HTML 拦截页,HTTP 状态仍是 200(所以按状态码查会漏掉)。
  5. 响应头有 X-Content-Type-Options: nosniff,浏览器拒绝把 text/html 当 text/css 应用 → 整页无样式,而不是缺一两个文件。
  6. www 页面同源、Referer 是 www → 放行,拿到真 CSS。
  7. 普通模式因一年期 CSS 缓存命中,裸域页根本不发这个请求 → 看着正常;无痕没缓存 → 必撞。

「两边 HTML 完全相同却一个有样式一个没有」,分叉不在 HTML,在浏览器发 CSS 请求时那个 Referer。

六 为什么原来的「HTTPS 强制跳转」没生效

原片段:

# ---- HTTPS 强制跳转(必须排在缓存规则之前)----
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(www\.)?511yj\.com$ [NC]
RewriteRule ^(.*)$ https://www.511yj.com%{REQUEST_URI} [L,R=301]

RewriteRule ^index\.php$ - [L]

第一行写的是「只有非 HTTPS 才执行」。用户输的是 https://,条件不成立,整条规则被跳过。于是裸域在 443 上原样返回页面,地址栏还停在 511yj.com。

七 修复:.htaccess 补三行 301

先备份:

copy C:\xampp\htdocs\.htaccess C:\xampp\htdocs\.htaccess.bak

把第六节那段整段替换成下面这样,位置保持在 # BEGIN WordPress 块内、HTTPS 强跳之后、Super Static Cache 之前:

# ---- HTTP → HTTPS + www(原来这条,一个字不动)----
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(www\.)?511yj\.com$ [NC]
RewriteRule ^(.*)$ https://www.511yj.com%{REQUEST_URI} [L,R=301]

# ---- HTTPS 但仍是裸域 → 补跳 www(新增)----
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} ^511yj\.com$ [NC]
RewriteRule ^(.*)$ https://www.511yj.com%{REQUEST_URI} [L,R=301]

RewriteRule ^index\.php$ - [L]

三个容易抄错的点

  • 条件要跟着新行重写一遍。RewriteCond 只管紧挨着它的那一条 RewriteRule,不会继承上面那组,所以新行前面必须再写两条 Cond。
  • 第二条 Host 正则不要带 (www\.)?。写成 ^(www\.)?511yj\.com$ 的话,https://www.511yj.com 也会命中、自己跳自己,直接无限重定向。只匹配纯裸域 ^511yj\.com$。
  • 沿用 %{REQUEST_URI} 即可,路径和查询串都会带过去,不用加 QSA。

逻辑就两条并列:http 来的 → 上一条跳走;https 但裸域 → 新条跳走;https://www.511yj.com 两条都不命中,正常往下走静态缓存。

运行时前提:第二条依赖 %{HTTPS} 在 443 vhost 里确实等于 on。标准 mod_ssl + SSLEngine on 下成立;XAMPP 个别配置会让它恒为 off。若验证时 301 没出来,不用改别的,把 RewriteCond %{HTTPS} on 这一行直接删掉即可 —— 剩下 ^511yj\.com$ 一条就够,http 裸域已被第一条 [L] 抢先跳走。二选一,别两版叠加。

八 验证:三条读数,缺一不可

curl.exe -sI https://511yj.com/ | findstr /i /c:"HTTP/" /c:"location"

curl.exe -sI https://www.511yj.com/ | findstr /i /c:"HTTP/" /c:"location"

curl.exe -sIL -o nul -w "final=%{url_effective} code=%{http_code}\n" https://511yj.com/
命令 期望 说明
第一条 HTTP/1.1 301 Moved Permanently + Location: https://www.511yj.com/ 裸域补跳生效
第二条 HTTP/1.1 200 OK、没有 Location 专门验没有自跳循环
第三条 final=https://www.511yj.com/ code=200 最终落到 www

最直接的一条其实是浏览器:开个新的无痕窗口(别用之前那个,避免 301 缓存干扰)打开 https://511yj.com,地址栏跳成 www、样式齐全,就结束了。

ECS 上只用只读命令确认文件真落盘了(备份 ≠ 已写入):

findstr /i /c:"补跳 www" /c:"%{HTTPS} on" C:\xampp\htdocs\.htaccess

能看到那三行才算改好。.htaccess.bak 会被 <FilesMatch "^\.ht"> 挡住,不会被下载,备份留着放心。

九 踩坑集:包括最后那两条 curl 报错

坑 1 · 把文档里的省略号原样粘进 CMD

复测时执行了这样一行:

C:\Users\zcp52>curl.exe ... -H "Referer: https://511yj.com/" ...style.css
curl: (3) URL rejected: Bad hostname
curl: (6) Could not resolve host: ...style.css

原因很简单:教程里写的 ... 是省略占位,表示「中间那一长串参数」,不是命令的一部分。原样粘进 CMD 后,curl 把 ... 当成字面量:

  • (3) URL rejected: Bad hostname —— ... 不是合法主机名,URL 解析阶段就被拒了。
  • (6) Could not resolve host: ...style.css —— ...style.css 被当成另一个 URL 去解析,DNS 里当然没有这个主机。

这不是网站问题、不是 DNS 问题、跟 ECS 的 DNS 指向 127.0.0.1 也毫无关系。要复测就贴第四节里带完整 URL 的那两条命令。

坑 2 · 修复后别再用「手工伪造裸域 Referer」自证失败

即使把 URL 写全,这条命令在修复后大概率仍返回 text/html 5758 —— 因为你人为造出了一个真实浏览器现在根本不会发出的 Referer。云锁按 Referer 判断,它拦得没错。判断修复是否成功,只看 301 的 Location 和无痕窗口,不要用这条命令推翻结论。

坑 3 · 两份首页快照不能当判据

抓取服务里 511yj.com 那份是完整渲染(含导航、新文列表),www 那份是正文摘要 —— 这是解析深度不同,且它记的是原始请求 URL、不记 301 跟随结果。301 属于 HTTP 响应头,只认 Location,正文内容一律不看。修复后裸域连内容都不会单独返回,更不存在「两份 HTML」。

坑 4 · .htaccess 里看着像重复的地方,别顺手清理

  • RewriteEngine On / RewriteBase / 出现两次(WordPress 外层 + Super Static Cache 内层),是插件生成的冗余,Apache 重复声明无害。
  • <IfModule mod_rewrite.c> 套了一层,恒为真,能跑。
  • <Ifmodule mod_headers.c> 大小写混用、header set 小写,Apache 指令不区分大小写。
  • <IfModule mod_headers.c> 在顶部和缓存段各出现一次,是并列不是嵌套,顶部那个已闭合。
  • SetEnvIf 属于 mod_setenvif 却写在 mod_headers 判断里 —— 能工作但不规范,两个模块默认都加载,实测响应头一直在。改它收益为零、风险不为零,别碰。

坑 5 · 可选优化,不是故障原因

ExpiresByType text/css "access plus 1 year" 建议顺手改短(比如 1 个月),以后再遇到资源类问题不用靠无痕才能发现。跟这次无样式没有因果关系,不急。

十 与证书续订的关系(附一句确认)

这次改动和 win-acme 续期不是一层:证书 / ECN / 出站链路 / junction 属于网络与文件层,本问题属于 Host 规范化 + WAF 防盗链 + 响应头 层,别混着查。

唯一需要确认的:ACME 的 /.well-known/acme-challenge/ 会被这个 301 带到 www,Let's Encrypt 允许跟随 301;之前建的目录联接让 C:\xampp\htdocs 与 C:\xampp\htdocs\bbs 读的是同一份 token 文件,自测过 bbs=200 size=4。不影响下次自动续期,Certificates_bak 保持改名别还原。

十一 命令速查

用途 命令 在哪跑
备份配置 copy C:\xampp\htdocs\.htaccess C:\xampp\htdocs\.htaccess.bak ECS
确认新增规则落盘 findstr /i /c:"补跳 www" /c:"%{HTTPS} on" C:\xampp\htdocs\.htaccess ECS
裸域是否 301 curl.exe -sI https://511yj.com/ | findstr /i /c:"HTTP/" /c:"location" 本地电脑
www 是否无自跳循环 curl.exe -sI https://www.511yj.com/ | findstr /i /c:"HTTP/" /c:"location" 本地电脑
跟随跳转后的最终 URL curl.exe -sIL -o nul -w "final=%{url_effective} code=%{http_code}\n" https://511yj.com/ 本地电脑
两域首页 link 对比 curl.exe -s --compressed https://511yj.com/ | findstr /i /c:"<link" 本地电脑
响应头对比 curl.exe -sI https://511yj.com/ | findstr /i /c:"content-security" /c:"content-encoding" /c:"x-content-type" /c:"location" 本地电脑
Referer 对照实验(修复前定位用) 见第四节两条带 -H "Referer: ..." 的完整命令 本地电脑
缓存文件清点 dir /s /b C:\xampp\htdocs\*index.html.gz 2>nul ECS

本文所有结论均来自本机 CMD 实测读数;被推翻的假设也一并保留,便于下次遇到同类「两边看起来一样却表现不同」的问题时对照。

分享到:

用微信扫一扫,分享给朋友


发布日期:

所属分类: SEO 网站运营 标签:



下一篇:

没有了,已经是最新文章