.htaccess 配置实战:301 重定向、强制 HTTPS、防盗链与目录保护
用 .htaccess 给 Apache 站点配 301 重定向、强制 HTTPS、防盗链、自定义 404 和目录保护。讲清每条规则的写法、顺序与坑,附一段可直接用的配置示例。
.htaccess 配置实战:301 重定向、强制 HTTPS、防盗链与目录保护
接手过一个跑在共享虚拟主机上的老站,客户只给了一个 FTP 账号,httpd.conf 碰都碰不到。要把全站从 http 切到 https,我能动的地方只有网站根目录里那个 .htaccess。改完一存,下一次请求 Apache 就读了进去,全站跳转立刻生效。这就是 .htaccess 的价值:它是 Apache 留给你的、不需要重启服务器、不需要管理员权限的那块配置入口。
下面把日常最常用的几类规则拆开讲,每一类都给出能直接抄的写法,以及我踩过的坑。
.htaccess 到底是什么
.htaccess 是 Apache 的分布式配置文件,放在哪个目录,它的规则就只管那个目录及其子目录。它由 mod_rewrite、mod_deflate、mod_expires、mod_headers 这些模块负责解析。
要注意两点。第一,它是 Apache 专有的,Nginx 完全不认这个文件,Nginx 的等价配置得写进 server 块。第二,它每次请求都会被读一遍,所以规则越多、目录层级越深,理论上越慢,真正在乎性能且能改 server config 的场景,优先用 VirtualHost。但对绝大多数共享主机用户来说,.htaccess 是唯一能落地的地方。
301 重定向:RewriteRule 的标准写法
301 是「永久重定向」,告诉搜索引擎旧地址已经永久搬走,把权重转移到新地址。这是 SEO 场景里最常用的一条。一定不要用 302,302 是临时跳转,Google 会继续收录旧 URL。
把整个旧目录重定向到新地址:
RewriteEngine On
RewriteRule ^old-page\.html$ /new-page.html [R=301,L]
R=301 指定返回 301 状态码,L 表示这是最后一条规则,匹配后不再往下走。如果要把一整个旧目录整体搬走:
RewriteRule ^blog/(.*)$ /articles/$1 [R=301,L]
$1 捕获括号里匹配到的那段路径,原样拼到新地址后面,旧链接结构能完整迁移过去。
强制 HTTPS:一段可以直接用的配置
这是我用得最多的一段。它的作用是:任何 http 请求都一跳跳到对应的 https 地址,不丢路径、不丢查询参数。
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
逐行说明:RewriteCond %{HTTPS} off 是条件,只有当前请求不是 https 时才触发下面的规则;%{HTTP_HOST} 取当前域名,%{REQUEST_URI} 取完整路径加查询串,所以用户访问 http://example.com/page?id=3,会被精准 301 到 https://example.com/page?id=3。
配完用 curl -I http://example.com/page 验证,确认只返回一个 301,而不是反复跳转的死循环。死循环最常见的成因是同时启用了「强制 www」和「去掉 www」两条互相打架的规则。
规则顺序很关键
Apache 从上到下执行 mod_rewrite 规则,遇到 [L] 就停。所以顺序错了,后面的规则可能根本走不到。正确的排法是:
RewriteEngine → 强制 HTTPS → www 规范化 → 防盗链 → 应用层 rewrite。
HTTPS 跳转必须排在最前面,否则用户可能先被应用规则消化掉、再也轮不到协议跳转。mod_deflate、mod_expires、Header 这类非 rewrite 指令彼此独立,放哪都行,按模块分组只是为了好读。
防盗链:别让别人白烧你的流量
如果有人把你的图片直接嵌在他的页面里,每次别人的访客打开,消耗的都是你的带宽。防盗链通过检查 Referer 头来拦截:
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?example\.com [NC]
RewriteRule \.(jpg|png|gif|webp)$ - [F]
!^$ 放行直接访问(没有 Referer 的情况,比如用户在地址栏直接打开图片),第二条 RewriteCond 放行来自你自己域名的请求,其余来源的图片请求一律 [F] 返回 403。也可以把 [F] 换成一张 1px 占位图,让盗链方的页面显示破图。
自定义 404 与目录保护
换掉默认那个丑陋的报错页,只要一行:
ErrorDocument 404 /404.html
ErrorDocument 500 /500.html
路径用站点根目录的绝对路径。注意 404 页面本身别再触发 404,否则会陷进递归。
目录保护是另一类常见需求,比如把后台或测试目录用账号密码挡住:
AuthType Basic
AuthName "Restricted Area"
AuthUserFile /var/www/example.com/.htpasswd
Require valid-user
这里的关键是 .htpasswd 文件,它存的是用户名和加密后的密码,不能手写明文。生成这个文件可以用 htpasswd 生成器,填好用户名密码就能拿到符合 Apache 格式的加密行,直接贴进文件即可。
几个一定要避开的坑
一个多余的引号、一条语法错的指令,就能把整站打成 500 Internal Server Error,而浏览器只会给你一句干巴巴的报错,不给任何线索。改之前务必备份,出问题就把旧文件名换回来。有 shell 权限的话,apachectl configtest 能在生效前帮你抓出语法错误。
另一个常见误区是把 HTML 也像图片那样缓存一年,部署后访客拿到的还是旧页面。HTML 保持 1 小时以内,静态文件名带版本号,才是稳妥做法。
手写这些规则容易写错顺序、漏掉 <IfModule> 包裹导致模块缺失直接 500。我自己现在都是先用 .htaccess 生成器 把 HTTPS、缓存、防盗链这些块勾出来,它会按正确顺序拼好、每条规则带中文注释,再复制下来按需微调,比从零敲省心也更不容易出错。
Made by Toolora · Updated 2026-06-13