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 的页面。改完后用无痕窗口走一遍:打开首页 → 点进帖子 → 发一个新帖 → 上传一个附件 → 退出重登,五个动作走完才算真配好。