1.4 伪静态、CDN 与 HTTPS 配置
三件让站点"像个正经网站"的外围配置,一次配好。
1.4.1 伪静态到底在解决什么
Discuz! 是 CGI 时代的产物,入口是 forum.php、home.php、portal.php 这类脚本文件,用户点一下请求一次 PHP,默认 URL 长这样:
forum.php?mod=viewthread&tid=12345
难看是一层,更实际的问题是搜索引擎收录和移动端分享体验。伪静态就是把它改写成 thread-123-1-1.html 这样的路径式 URL:带主题关键词利于收录、二次分享不丢参数、去掉 .php 后缀看不出技术栈。
原理是服务器收到请求先看有没有匹配的静态文件,匹配不到就转给 forum.php 入口脚本,同时把原始参数还原进 $_GET。打个比方,这就像给老式总机装了一排快捷拨号键——你按 1 号键,话务员照样转接到同一个分机。
1.4.2 Nginx 下的规则
Nginx 不读 .htaccess,规则写在站点配置文件里(宝塔在「网站 → 设置 → 配置文件」,路径一般是 /www/server/panel/vhost/nginx/你的站点.conf)。后台伪静态页面也提供对应规则,复制过去即可:
# Discuz! 伪静态规则,放到 server { } 块内
rewrite ^([^\.]+)/([^\.]+)\.html$ /forum.php?mod=$1&tid=$2 last;
rewrite ^([^\.]+)/([^\.]+)/([^\.]+)\.html$ /forum.php?mod=$1&fid=$2&page=$3 last;
rewrite ^portal-(.+)-(\d+)-(\d+)\.html$ /portal.php?mod=article&aid=$2&page=$3 last;
rewrite ^([^/]+)/space$ /home.php?mod=space&uid=$1 last;
改完必须重载:
nginx -t # 先测语法,这一步能挡掉大部分手误
nginx -s reload
nginx -t 千万别跳。少个分号、多余空格,Nginx 会直接拒绝加载,那时整站全挂,不只是伪静态失效。
1.4.3 Apache 与 IIS 下的写法
Apache 用 .htaccess(前提是 AllowOverride All 打开):
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ forum.php last
IIS 用 web.config + URL Rewrite 模块。本书记法对尖括号做了转义,写进文件时请还原:
<rule name="Discuz" stopProcessing="true">
<match url="^(.*)$" ignoreCase="false" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
<action type="Rewrite" url="forum.php" />
</rule>
放在 rewrite/rules 节点下,并确认应用池里「web.config 重写」已允许,否则整段被无视。
1.4.4 伪静态不生效的六个原因
先记住一条关键认知:伪静态必须两边配合。后台「全局 → 站点信息 → 站点设置」的开关决定"生成什么 URL",服务器规则决定"认出这种 URL",只开一边链接就断了。
| 现象 | 原因 | 处理 |
|---|---|---|
URL 还是 .php?mod= |
后台开关没开 | 站点设置里勾选伪静态 |
| 后台开了但 404 | 规则没加载 | nginx -t 后 reload;确认写在 server 块内 |
| 部分页生效、部分不生效 | 规则不全 | 对照官方完整规则逐条补齐 |
| 图片、CSS 也被转给 PHP | 缺少"文件存在则放行"判断 | 保留 !-f / !-d 条件 |
| 登录后跳转丢失参数 | 跳转链接没带 goto |
检查表单提交来源与跳转设置 |
| 改完配置没反应 | 改错文件或有多个 server 块 |
用 nginx -T 看完整生效配置 |
排查顺序固定:先开后台开关,再改服务器规则,然后清缓存,最后看错误日志。 "清缓存"最常被忘——伪静态 URL 写进 data/cache/,不清缓存前台仍按旧链接跳。
1.4.5 HTTPS 与强制跳转
证书现在有免费方案,Let's Encrypt 或各云厂商的免费 DV 证书都够用。Nginx 侧配置:
# 80 端口统一跳 HTTPS
server {
listen 80;
server_name bbs.example.com;
return 301 https://$host$request_uri;
}
# 443 端口主站
server {
listen 443 ssl http2;
server_name bbs.example.com;
ssl_certificate /www/server/panel/vhost/cert/bbs.example.com/fullchain.pem;
ssl_certificate_key /www/server/panel/vhost/cert/bbs.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
# HSTS:告诉浏览器以后只走 HTTPS
add_header Strict-Transport-Security "max-age=31536000" always;
}
配好后后台还要同步改:把「全局 → 站点信息」里的站点地址改成 https://你的域名,否则站内生成的链接还是 http://,出现"页面跳走了但外链还是 http"的混合状态,改完清一次缓存。
1.4.6 接了 CDN 之后必改的两项
CDN 把请求先挡在边缘节点,源站看到的是节点而不是真实用户,这带来两个必改项。
第一项:真实 IP。 不改的话后台的 IP 记录、在线列表、ip 封禁全乱——所有人显示同一个节点 IP。
# 真实 IP:只信任 CDN 厂商公布的回源网段
set_real_ip_from 0.0.0.0/0; # 生产环境务必换成准确网段
real_ip_header X-Forwarded-For;
real_ip_recursive on;
fastcgi_param HTTP_X_FORWARDED_PROTO $scheme;
set_real_ip_from 0.0.0.0/0 等于信任全世界,是图省事的写法。生产环境请从 CDN 控制台拿到准确的回源 IP 段一行行写清楚——否则伪造一个 X-Forwarded-For 头就能骗过你的封禁逻辑。
第二项:附件与静态资源走 CDN。 在「全局 → 上传设置」里把附件、头像、图片的 URL 改成 CDN 域名,同时在 CDN 侧配好 /data/attachment/、static/、template/ 的回源规则。X5.0 支持把对象存储做成插件接管,更彻底的做法是附件直传对象存储,源站连附件流量都碰不到。
1.4.7 Nginx 配置片段速查
| 配置片段 | 作用 | 常见坑 |
|---|---|---|
nginx -t |
检查配置语法 | 手写规则后必做,能拦下大部分 500 |
rewrite ... last; |
伪静态匹配并转交内部处理 | 必须放在 server 块内,放 location 外不生效 |
return 301 https://$host$request_uri; |
HTTP 强跳 HTTPS | 少了 $request_uri 会丢路径参数 |
real_ip_header X-Forwarded-For; |
取 CDN 回传的真实用户 IP | 必须配 set_real_ip_from,否则不生效 |
add_header Strict-Transport-Security |
浏览器强制 HTTPS | 一旦设了很难撤回,调试期先别加 |
client_max_body_size 50m; |
放开上传限制 | PHP 的 upload_max_filesize 要一起改 |
gzip on; + gzip_types |
压缩文本响应 | 图片别再压,纯浪费 CPU |
expires 30d; |
静态资源长缓存 | 改样式表后用户长时间看不到新效果 |
这三样东西要一次配到位再上线,别分几天慢慢配。分阶段改的过程中,搜索引擎会抓到一半 http 一半 https 的页面。改完后用无痕窗口走一遍:打开首页 → 点进帖子 → 发一个新帖 → 上传一个附件 → 退出重登,五个动作走完才算真配好。
