.htaccess 文件(Hypertext Access)是 Apache 网络服务器在每个请求时读取的一个小型按目录配置文件。它让网站所有者可以调整服务器行为,而无需接触主 httpd.conf —— 使其成为在共享托管和 DirectAdmin 环境中提供的主要定制工具。
从 URL 重定向和强制 HTTPS 到 GZIP 压缩、浏览器缓存、安全头和 PHP 设置覆盖,.htaccess 处理各种任务,否则这些任务需要服务器级别访问。本指南收集了最常用的 WordPress 网站和 PHP 网络应用程序的 .htaccess 命令,包含在 Apache 2.4 上测试的工作示例。
理解 .htaccess 如何工作
在添加任何指令之前,理解三个核心原则将为您节省几个小时的调试时间:
- 在每个请求上解析 — 不像在服务器启动时加载一次的
httpd.conf,Apache 在每个 HTTP 请求上重新读取 .htaccess。这意味着更改立即生效,无需重启服务器,但太多规则可能会给每个请求增加可测量的开销。 - 级联范围 —
/public_html/中的 .htaccess 适用于整个网站。/public_html/shop/内的 .htaccess 仅适用于/shop/下的 URL。Apache 从根目录向下合并文件到请求目录,深层文件覆盖父文件的相同指令。 - 必须启用 AllowOverride — 如果服务器设置
AllowOverride None,Apache 将完全忽略 .htaccess。大多数共享托管提供商,包括 AsiaGB DirectAdmin 托管,默认启用此功能。如果您的指令没有效果,请首先验证此设置。
以 # 开头的行是注释,没有效果。慷慨地使用注释使未来的维护变得更容易,特别是当您有多个覆盖不同目的的规则块时。
WordPress 永久链接块 — 基础
WordPress 依赖 mod_rewrite 将所有不对应真实文件或目录的请求路由到 index.php,然后处理 WordPress 路由逻辑。当您在设置 > 永久链接下保存永久链接设置时,WordPress 仪表板会自动生成此块。以下是每行所做的:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
RewriteBase / 为相对规则设置基本路径。如果 WordPress 安装在诸如 /blog/ 之类的子目录中,请将其更改为 RewriteBase /blog/ 并将最终规则更新为 RewriteRule . /blog/index.php [L]。两条 RewriteCond 行确保对实文件(图像、CSS、JS)和实际目录的请求绕过 WordPress 路由并由 Apache 直接提供。永远不要删除这些条件 —— 这样做会破坏静态资产提交。
重定向 — 301 和 HTTPS 强制
重定向是最常见的 .htaccess 任务之一。对于任何生产网站最关键的两个是强制 HTTPS 和选择规范域(www vs 非www)。两者都应该从第一天开始设置。
强制 HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
将 www 重定向到非 www(规范非 www)
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.yourdomain\.com [NC]
RewriteRule ^(.*)$ https://yourdomain.com/$1 [R=301,L]
组合:在一次传递中强制 HTTPS + 非 www
组合两个规则可防止双重重定向(序列中的两个 301),这会浪费延迟并稀释链接权益:
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteRule ^(.*)$ https://yourdomain.com/$1 [R=301,L]
[OR] 标志意味着当任一条件为真时规则触发。所有四个入口点(http/https × www/non-www)都在单一跃点中重定向到规范 URL。
GZIP 压缩 — 更小的传输、更快的页面
GZIP 在将文本资产发送到浏览器之前对其进行压缩,通常将 HTML、CSS 和 JavaScript 减少 60–80%。这是可用的最高影响性能优化之一,对现代浏览器没有负面影响。
<IfModule mod_deflate.c> AddOutputFilterByType DEFLATE text/plain AddOutputFilterByType DEFLATE text/html AddOutputFilterByType DEFLATE text/xml AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE application/xml AddOutputFilterByType DEFLATE application/xhtml+xml AddOutputFilterByType DEFLATE application/rss+xml AddOutputFilterByType DEFLATE application/javascript AddOutputFilterByType DEFLATE application/x-javascript AddOutputFilterByType DEFLATE application/json # Skip already-compressed formats SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|webp|svg|ico|zip|gz|bz2|mp4|mp3)$ no-gzip dont-vary </IfModule>
用以下命令验证 GZIP 是否活跃:curl -H "Accept-Encoding: gzip" -I https://yourdomain.com/。如果响应中包含 Content-Encoding: gzip 标头,说明已启用。
浏览器缓存 — 减少重复下载
浏览器缓存告诉浏览器在本地保留静态资源的时间长度。在缓存时间内回访的用户将跳过下载图像、CSS 和字体,从而实现几乎即时的页面加载,并降低服务器的带宽消耗。
<IfModule mod_expires.c> ExpiresActive On ExpiresDefault "access plus 1 month" # Images — cache for 1 year ExpiresByType image/jpeg "access plus 1 year" ExpiresByType image/png "access plus 1 year" ExpiresByType image/gif "access plus 1 year" ExpiresByType image/webp "access plus 1 year" ExpiresByType image/svg+xml "access plus 1 year" ExpiresByType image/x-icon "access plus 1 year" # CSS and JavaScript — cache for 1 month ExpiresByType text/css "access plus 1 month" ExpiresByType application/javascript "access plus 1 month" ExpiresByType application/x-javascript "access plus 1 month" # Web fonts — cache for 1 year ExpiresByType font/woff2 "access plus 1 year" ExpiresByType font/woff "access plus 1 year" ExpiresByType application/font-woff2 "access plus 1 year" # HTML — short cache ExpiresByType text/html "access plus 1 hour" ExpiresByType application/rss+xml "access plus 1 hour" </IfModule> <IfModule mod_headers.c> Header append Cache-Control "public" </IfModule>
缓存破坏提示:长缓存生命周期强大但会产生问题——当更新 CSS 或 JS 文件时,用户看到旧版本直到缓存过期。使用缓存破坏来解决:在资源 URL 中附加版本查询字符串,例如 style.css?v=20260609。浏览器将新 URL 视为不同文件并立即下载最新版本,完全绕过旧缓存条目。
安全标头
安全标头是 HTTP 响应标头,指示浏览器如何处理内容,防止整个类别的漏洞,如点击劫持、MIME 嗅探和跨站脚本。添加它们是免费的,对性能没有成本,可大幅提高安全态势。
<IfModule mod_headers.c> # Prevent framing from other origins (clickjacking protection) Header always set X-Frame-Options "SAMEORIGIN" # Prevent MIME type sniffing Header always set X-Content-Type-Options "nosniff" # Legacy XSS protection for older browsers Header always set X-XSS-Protection "1; mode=block" # Control referrer information sent to third parties Header always set Referrer-Policy "strict-origin-when-cross-origin" # HTTP Strict Transport Security — set only after HTTPS is confirmed working Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" </IfModule>
阻止 xmlrpc.php(WordPress)
WordPress 的 xmlrpc.php 是一个遗留的远程发布接口,攻击者常用于蛮力密码攻击和放大 DDoS 攻击。如果不使用 Jetpack 或任何 XML-RPC 客户端,请完全阻止它:
<Files xmlrpc.php> Order Deny,Allow Deny from all </Files>
在 /uploads/ 中阻止 PHP 执行(WordPress)
即使文件上传漏洞允许攻击者将 PHP 文件放入上传目录,此规则也会阻止 Apache 执行它。在 wp-content/uploads/ 内创建单独的 .htaccess 文件:
<FilesMatch "\.php$"> Order Allow,Deny Deny from all </FilesMatch>
PHP 设置覆盖
在无法直接编辑全局 php.ini 的共享托管中,可以通过 .htaccess 使用 php_value 和 php_flag 指令按目录覆盖许多 PHP 设置。AsiaGB DirectAdmin 托管支持此功能。
# Increase memory limit for WordPress or heavy PHP apps php_value memory_limit 256M # Increase file upload limits php_value upload_max_filesize 64M php_value post_max_size 64M # Increase maximum script execution time (seconds) php_value max_execution_time 300 # Hide PHP errors from public view (use on production) php_flag display_errors Off # Log errors to error_log instead of displaying them php_flag log_errors On # Set timezone for date/time functions php_value date.timezone "Asia/Bangkok" # Session security hardening php_value session.cookie_httponly 1 php_value session.cookie_secure 1
如果添加 php_value 指令导致 500 错误,托管环境不允许通过 .htaccess 进行 PHP 覆盖。在这种情况下,尝试在同一目录中放置 php.ini 或 user.ini 文件——许多共享托管设置支持这些替代方案之一。
防盗链和访问控制
防盗链发生在另一个网站使用您的服务器 URL 嵌入您的图像时,消耗您的带宽而不为您的访问者提供服务。可以使用 HTTP Referer 标头来阻止这种情况:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?yourdomain\.com [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp|svg)$ - [F,NC]
</IfModule>
第一个条件允许空 referer(直接访问、curl、RSS 阅读器)。第二个条件允许来自您自己域的请求。[F] 标志返回 403 禁止响应,而不是提供图像。将 yourdomain.com 替换为您的实际域名。
快速参考表
需要特定指令类别时使用此表作为快速查找:
| 分类 | 关键指令 | Apache 模块 | 用途 |
|---|---|---|---|
| 重定向 | Redirect 301 |
mod_alias | 永久 URL 移动,保留 SEO |
| 重写 | RewriteRule / RewriteCond |
mod_rewrite | URL 模式转换、WordPress 路由 |
| GZIP | AddOutputFilterByType DEFLATE |
mod_deflate | 压缩响应、降低带宽 |
| 缓存 | ExpiresByType |
mod_expires | 按文件类型设置浏览器缓存生命周期 |
| 标头 | Header always set |
mod_headers | 安全标头、HSTS、CORS |
| PHP | php_value / php_flag |
mod_php | 按目录覆盖 php.ini 设置 |
| 访问控制 | Order Deny,Allow / <Files> |
mod_access | 阻止文件、IP 或用户代理 |
| 错误 | ErrorDocument |
core | 为 4xx/5xx 提供自定义错误页面 |
最佳实践和常见陷阱
这些指南将防止使用 .htaccess 时最常见的错误:
- 始终先备份 — 在每次更改前下载当前 .htaccess。如果出问题,可通过 FTP 或 DirectAdmin 文件管理器在几秒内恢复。
- 将块包装在 IfModule 中 — 使用
<IfModule mod_xxx.c>可防止在服务器上未加载所需模块时出现 500 错误。 - 规则顺序重要 — Apache 从上到下处理规则。广泛规则(HTTPS 强制)应首先出现。特定规则应使用
[L]标志在匹配后停止处理,防止意外的下游规则交互。 - 在隐身模式下测试 — 301 重定向被浏览器缓存。在私有/隐身窗口中测试会绕过此缓存,显示更改后的实际服务器行为。
- 检查错误日志 — DirectAdmin 在"日志 > 错误日志"下提供 Apache 错误日志访问权限。如果指令导致 500 错误,日志将显示确切的行和原因。
- 注意重定向循环 — 匹配自己输出的规则将无限循环。使用
curl -L -I跟踪重定向并计数。来自同一源 URL 的超过两个跳转表示需要修复的循环或链。 - 不要与 WordPress 冲突 — WordPress 在其
# BEGIN WordPress / # END WordPress块内管理自己的路由。将自定义规则添加到此块上方或下方,永远不要在块内添加,以防止 WordPress 仪表板在重新生成永久链接规则时覆盖您的更改。
常见问题
.htaccess 在所有类型的网络托管上都能工作吗?
.htaccess 仅在基于 Apache 的网络服务器上工作,涵盖大多数共享托管和 VPS 环境,包括 AsiaGB DirectAdmin 托管。如果服务器运行 Nginx,必须改为在 nginx.conf 中配置指令。LiteSpeed 服务器也支持几乎所有 Apache .htaccess 指令。
编辑 .htaccess 后网站出现 500 内部服务器错误——我该怎么办?
来自 .htaccess 的 500 错误几乎总是由语法错误引起的:拼写错误的指令、标志周围缺少方括号(如 [L])或 mod_rewrite 未加载。检查 DirectAdmin 中的错误日志(日志 > 错误日志)以查看确切消息。还可以运行 curl -I https://yourdomain.com 来检查 HTTP 响应。在进行更改前始终保留原始 .htaccess 的备份。
WordPress 需要什么特殊的 .htaccess 配置?
WordPress 需要一个 mod_rewrite 块来将所有请求路由到 index.php,WordPress 仪表板在保存永久链接设置时自动生成该块。除此之外,常见做法是添加 GZIP 压缩以减少文件大小、浏览器缓存以提高重复访问速度、阻止访问 xmlrpc.php 以防止蛮力攻击,以及阻止 /uploads/ 目录内的 PHP 执行以防止恶意软件执行。
子目录中的多个 .htaccess 文件如何交互?
Apache 从文档根目录向下合并 .htaccess 文件到请求目录。沿路径的每个文件按顺序处理,深层文件对相同指令覆盖父文件。对于 WordPress,保持根 .htaccess 专注于 WordPress 永久链接路由,并在 wp-content/uploads/ 中放置单独的 .htaccess 仅用于阻止 PHP 执行。这种分离使维护更容易,并降低规则冲突的风险。
由 AsiaGB 提供的功能齐全的 DirectAdmin 托管
AsiaGB 托管支持 DirectAdmin、PHP 8.3、MySQL 和完整的 .htaccess 访问权限。计划从 500 泰铢/年起,99% 正常运行时间。
查看托管计划