.htaccess 文件(Hypertext Access)是 Apache 网络服务器在每个请求时读取的一个小型按目录配置文件。它让网站所有者可以调整服务器行为,而无需接触主 httpd.conf —— 使其成为在共享托管和 DirectAdmin 环境中提供的主要定制工具。

从 URL 重定向和强制 HTTPS 到 GZIP 压缩、浏览器缓存、安全头和 PHP 设置覆盖,.htaccess 处理各种任务,否则这些任务需要服务器级别访问。本指南收集了最常用的 WordPress 网站和 PHP 网络应用程序的 .htaccess 命令,包含在 Apache 2.4 上测试的工作示例。

理解 .htaccess 如何工作

在添加任何指令之前,理解三个核心原则将为您节省几个小时的调试时间:

以 # 开头的行是注释,没有效果。慷慨地使用注释使未来的维护变得更容易,特别是当您有多个覆盖不同目的的规则块时。

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 在所有类型的网络托管上都能工作吗?

.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% 正常运行时间。

查看托管计划

查看泰国虚拟主机全部套餐 →