DevToolBox免费
博客

.htaccess 重定向速查表:可复制粘贴的示例

10 分钟阅读作者 DevToolBox

.htaccess 文件是 Apache Web 服务器最强大的配置工具之一。它可以控制重定向、强制 HTTPS、设置安全头、管理缓存等,无需修改主服务器配置。本全面的 .htaccess 重定向速查表提供了可直接复制粘贴的生产级示例,涵盖所有常见场景。每个代码片段都包含详细注释。

基本重定向

重定向是 .htaccess 文件最常见的用途。无论是移动单个页面、重组整个目录还是迁移到新域名,Apache 的 RedirectRewriteRule 指令都能轻松实现。始终使用 301(永久)重定向以便 SEO 权重传递到新 URL。

重定向单个 URL

# Redirect a single URL (301 permanent)
Redirect 301 /old-page.html https://example.com/new-page.html

# Using RewriteRule for more control
RewriteEngine On
RewriteRule ^old-page\.html$ /new-page.html [R=301,L]

# Redirect with pattern matching (e.g., old product URLs)
RewriteRule ^products/([0-9]+)\.html$ /shop/item/$1 [R=301,L]

重定向整个目录

# Redirect entire directory to new location
RedirectMatch 301 ^/blog/(.*)$ https://example.com/articles/$1

# Using RewriteRule (preserves subdirectory structure)
RewriteEngine On
RewriteRule ^blog/(.*)$ /articles/$1 [R=301,L]

# Redirect directory but keep filenames
RewriteRule ^old-folder/(.+)$ /new-folder/$1 [R=301,L]

域名到域名重定向

# Redirect entire old domain to new domain
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?olddomain\.com$ [NC]
RewriteRule ^(.*)$ https://newdomain.com/$1 [R=301,L]

# Redirect specific domain alias to primary domain
RewriteEngine On
RewriteCond %{HTTP_HOST} ^olddomain\.net$ [NC,OR]
RewriteCond %{HTTP_HOST} ^olddomain\.org$ [NC]
RewriteRule ^(.*)$ https://newdomain.com/$1 [R=301,L]

HTTPS 强制跳转

强制 HTTPS 对安全和 SEO 至关重要。Google 将 HTTPS 作为排名信号,现代浏览器会对不安全的 HTTP 连接发出警告。这些规则使用 mod_rewrite 将所有 HTTP 流量重定向到 HTTPS,并提供处理 www 前缀的选项。

HTTP 到 HTTPS(不含 www)

# Force HTTPS (redirect HTTP to HTTPS, non-www)
RewriteEngine On

# Redirect www to non-www
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]

# Redirect HTTP to HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]

HTTP 到 HTTPS(含 www)

# Force HTTPS with www prefix
RewriteEngine On

# Redirect non-www to www
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]

# Redirect HTTP to HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]

强制非 www 并使用 HTTPS

# Force non-www + HTTPS in a single pass
# Works on shared hosting and most Apache setups
RewriteEngine On

# Handle both www removal and HTTPS enforcement together
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]

RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

# Alternative: Using environment variables (some hosts)
# RewriteCond %{ENV:HTTPS} !on
# RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

尾部斜杠处理

不一致的尾部斜杠会造成重复内容问题,影响 SEO。搜索引擎将 /about/about/ 视为不同的 URL。选择一种风格并在整个站点中一致地执行。

添加尾部斜杠

# Add trailing slash to all URLs (except files with extensions)
RewriteEngine On

# Only apply to URLs without a file extension
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !\.[a-zA-Z0-9]{1,5}$
RewriteRule ^(.+[^/])$ %{REQUEST_URI}/ [R=301,L]

# Simpler version (may cause issues with some file types)
# RewriteRule ^(.*[^/])$ $1/ [R=301,L]

移除尾部斜杠

# Remove trailing slash from all URLs (except directories)
RewriteEngine On

# Do not remove trailing slash from actual directories
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [R=301,L]

# Remove trailing slash except for root URL
# RewriteCond %{REQUEST_URI} !^/$
# RewriteRule ^(.*)/$ /$1 [R=301,L]

查询字符串处理

重定向带查询字符串的 URL 需要特别注意。默认情况下,Apache 会将原始查询字符串追加到重定向目标。可以使用 QSA(查询字符串追加)和 ?(丢弃)标志来保留、丢弃或修改查询参数。

重定向并保留查询字符串

# Redirect preserving the original query string (default behavior)
# /search?q=test -> /find?q=test
RewriteEngine On
RewriteRule ^search$ /find [R=301,L]

# Redirect and APPEND additional query parameters (QSA flag)
# /page?id=5 -> /new-page?id=5&ref=old
RewriteRule ^page$ /new-page?ref=old [R=301,L,QSA]

# Match specific query string and redirect
RewriteCond %{QUERY_STRING} ^id=([0-9]+)$
RewriteRule ^product\.php$ /products/%1? [R=301,L]

重定向并丢弃查询字符串

# Redirect and DISCARD all query parameters
# /old-page?any=params -> /new-page (clean URL)
RewriteEngine On
RewriteRule ^old-page$ /new-page? [R=301,L]
# The trailing ? strips the query string

# Discard specific query parameters only
# /page?utm_source=x&id=5 -> /page?id=5 (strip tracking params)
RewriteCond %{QUERY_STRING} (^|&)utm_[^&]*
RewriteRule ^(.*)$ /$1? [R=301,L]

重定向并修改查询参数

# Rewrite query parameter to path segment
# /index.php?page=about -> /about
RewriteEngine On
RewriteCond %{QUERY_STRING} ^page=(.+)$
RewriteRule ^index\.php$ /%1? [R=301,L]

# Rewrite path segment to query parameter
# /category/electronics -> /shop.php?cat=electronics
RewriteRule ^category/([a-zA-Z0-9-]+)$ /shop.php?cat=$1 [L]

# Rename a query parameter
# /search?q=test -> /search?query=test
RewriteCond %{QUERY_STRING} ^q=(.+)$
RewriteRule ^search$ /search?query=%1 [R=301,L]

自定义错误页面

自定义错误页面通过提供有用信息来改善用户体验。ErrorDocument 指令允许为任何 HTTP 状态码定义自定义页面。

# Custom error pages
# Place error page files in your document root

# 404 Not Found - page does not exist
ErrorDocument 404 /errors/404.html

# 403 Forbidden - access denied
ErrorDocument 403 /errors/403.html

# 500 Internal Server Error
ErrorDocument 500 /errors/500.html

# 401 Unauthorized - authentication required
ErrorDocument 401 /errors/401.html

# 503 Service Unavailable - maintenance mode
ErrorDocument 503 /errors/maintenance.html

# You can also use inline messages (not recommended for production)
# ErrorDocument 404 "Page not found. Please check the URL."

# Or redirect to an external URL
# ErrorDocument 404 https://example.com/not-found

# ── Maintenance mode (redirect all traffic to maintenance page) ──
# Uncomment during maintenance, recomment when done
# RewriteEngine On
# RewriteCond %{REMOTE_ADDR} !^123\.456\.789\.000$  # Allow your IP
# RewriteCond %{REQUEST_URI} !/errors/maintenance.html$ [NC]
# RewriteCond %{REQUEST_URI} !\.(css|js|png|jpg|gif|ico)$ [NC]
# RewriteRule ^(.*)$ /errors/maintenance.html [R=503,L]

通过 .htaccess 设置安全头

HTTP 安全头保护您的网站免受点击劫持、跨站脚本(XSS)和内容注入等常见攻击。通过 .htaccess 添加这些头是最简单的方法,需要启用 mod_headers

# Security headers via .htaccess
# Requires mod_headers to be enabled: a2enmod headers

<IfModule mod_headers.c>

  # X-Frame-Options: Prevent clickjacking by blocking iframes
  # Options: DENY | SAMEORIGIN | ALLOW-FROM uri
  Header always set X-Frame-Options "SAMEORIGIN"

  # X-Content-Type-Options: Prevent MIME-type sniffing
  Header always set X-Content-Type-Options "nosniff"

  # X-XSS-Protection: Enable browser XSS filter (legacy)
  Header always set X-XSS-Protection "1; mode=block"

  # Referrer-Policy: Control referrer information
  Header always set Referrer-Policy "strict-origin-when-cross-origin"

  # Content-Security-Policy: Control resource loading
  # Customize the sources based on your site's needs
  Header always set Content-Security-Policy "default-src 'self'; \
    script-src 'self' 'unsafe-inline' https://cdn.example.com; \
    style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; \
    img-src 'self' data: https:; \
    font-src 'self' https://fonts.gstatic.com; \
    connect-src 'self' https://api.example.com; \
    frame-ancestors 'self';"

  # Strict-Transport-Security (HSTS): Force HTTPS for 2 years
  # Only add this if your site fully supports HTTPS
  Header always set Strict-Transport-Security \
    "max-age=63072000; includeSubDomains; preload"

  # Permissions-Policy: Disable unused browser features
  Header always set Permissions-Policy \
    "camera=(), microphone=(), geolocation=(), interest-cohort=()"

  # Remove X-Powered-By header (hides PHP/server version)
  Header unset X-Powered-By
  Header always unset X-Powered-By

</IfModule>

# Hide Apache version in server headers
ServerSignature Off

浏览器缓存规则

浏览器缓存通过告诉浏览器在本地存储静态资源,显著提高回访者的页面加载速度。mod_expires 模块自动设置 Cache-ControlExpires 头。

# Browser caching with mod_expires
# Enable the module: a2enmod expires

<IfModule mod_expires.c>
  ExpiresActive On

  # Default expiration: 1 month
  ExpiresDefault "access plus 1 month"

  # HTML files: short cache (content changes frequently)
  ExpiresByType text/html "access plus 1 hour"

  # CSS and JavaScript: long cache (use fingerprinted filenames)
  ExpiresByType text/css "access plus 1 year"
  ExpiresByType application/javascript "access plus 1 year"
  ExpiresByType text/javascript "access plus 1 year"

  # Images: cache for 1 month
  ExpiresByType image/jpeg "access plus 1 month"
  ExpiresByType image/png "access plus 1 month"
  ExpiresByType image/gif "access plus 1 month"
  ExpiresByType image/webp "access plus 1 month"
  ExpiresByType image/avif "access plus 1 month"
  ExpiresByType image/svg+xml "access plus 1 month"
  ExpiresByType image/x-icon "access plus 1 year"

  # Fonts: cache for 1 year
  ExpiresByType font/woff2 "access plus 1 year"
  ExpiresByType font/woff "access plus 1 year"
  ExpiresByType font/ttf "access plus 1 year"
  ExpiresByType application/font-woff2 "access plus 1 year"
  ExpiresByType application/font-woff "access plus 1 year"

  # JSON/XML data: short cache
  ExpiresByType application/json "access plus 1 hour"
  ExpiresByType application/xml "access plus 1 hour"

  # PDF and documents
  ExpiresByType application/pdf "access plus 1 month"
</IfModule>

# Alternative: Cache-Control headers with mod_headers
<IfModule mod_headers.c>
  # Immutable cache for fingerprinted assets
  <FilesMatch "\.(js|css)$">
    Header set Cache-Control "public, max-age=31536000, immutable"
  </FilesMatch>

  # Short cache for HTML
  <FilesMatch "\.html$">
    Header set Cache-Control "public, max-age=3600, must-revalidate"
  </FilesMatch>

  # No cache for dynamic content
  <FilesMatch "\.(php|cgi)$">
    Header set Cache-Control "no-store, no-cache, must-revalidate"
  </FilesMatch>
</IfModule>

Gzip / Brotli 压缩

压缩可将传输响应的大小减少 60-90%,显著提升页面加载速度。Apache 支持 Gzip(通过 mod_deflate)和 Brotli(通过 mod_brotli,需 Apache 2.4.26+)。

Gzip 压缩(mod_deflate)

# Gzip compression using mod_deflate
# Enable the module: a2enmod deflate

<IfModule mod_deflate.c>
  # Compress text-based content types
  AddOutputFilterByType DEFLATE text/plain
  AddOutputFilterByType DEFLATE text/html
  AddOutputFilterByType DEFLATE text/xml
  AddOutputFilterByType DEFLATE text/css
  AddOutputFilterByType DEFLATE text/javascript
  AddOutputFilterByType DEFLATE application/xml
  AddOutputFilterByType DEFLATE application/xhtml+xml
  AddOutputFilterByType DEFLATE application/rss+xml
  AddOutputFilterByType DEFLATE application/atom+xml
  AddOutputFilterByType DEFLATE application/javascript
  AddOutputFilterByType DEFLATE application/x-javascript
  AddOutputFilterByType DEFLATE application/json
  AddOutputFilterByType DEFLATE application/ld+json
  AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
  AddOutputFilterByType DEFLATE font/opentype
  AddOutputFilterByType DEFLATE font/ttf
  AddOutputFilterByType DEFLATE font/woff
  AddOutputFilterByType DEFLATE font/woff2
  AddOutputFilterByType DEFLATE image/svg+xml
  AddOutputFilterByType DEFLATE image/x-icon

  # Do not compress images (already compressed)
  SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|webp|avif)$ no-gzip

  # Handle browser quirks
  BrowserMatch ^Mozilla/4 gzip-only-text/html
  BrowserMatch ^Mozilla/4\.0[678] no-gzip
  BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

  # Add Vary header for proper caching
  Header append Vary Accept-Encoding
</IfModule>

Brotli 压缩(mod_brotli)

# Brotli compression using mod_brotli (Apache 2.4.26+)
# Enable the module: a2enmod brotli

<IfModule mod_brotli.c>
  # Compress text-based content types with Brotli
  AddOutputFilterByType BROTLI_COMPRESS text/plain
  AddOutputFilterByType BROTLI_COMPRESS text/html
  AddOutputFilterByType BROTLI_COMPRESS text/xml
  AddOutputFilterByType BROTLI_COMPRESS text/css
  AddOutputFilterByType BROTLI_COMPRESS text/javascript
  AddOutputFilterByType BROTLI_COMPRESS application/xml
  AddOutputFilterByType BROTLI_COMPRESS application/xhtml+xml
  AddOutputFilterByType BROTLI_COMPRESS application/javascript
  AddOutputFilterByType BROTLI_COMPRESS application/json
  AddOutputFilterByType BROTLI_COMPRESS application/ld+json
  AddOutputFilterByType BROTLI_COMPRESS font/opentype
  AddOutputFilterByType BROTLI_COMPRESS font/ttf
  AddOutputFilterByType BROTLI_COMPRESS font/woff
  AddOutputFilterByType BROTLI_COMPRESS font/woff2
  AddOutputFilterByType BROTLI_COMPRESS image/svg+xml

  # Brotli compression quality (0-11, default: 11)
  # Lower = faster compression, larger files
  # Higher = slower compression, smaller files
  BrotliCompressionQuality 6

  # Brotli window size (10-24, default: 22)
  BrotliCompressionWindow 22
</IfModule>

# Fallback: Use Gzip if Brotli is not available
# Both modules can coexist; Apache serves Brotli to
# browsers that support it and Gzip to others.

常见错误及修复方法

调试 .htaccess 问题可能令人沮丧。以下是开发者最常犯的错误及其解决方法,了解这些陷阱能为您节省大量排查时间。

无限重定向循环

最常见的错误是创建重定向循环,重写后的 URL 再次匹配同一规则。始终使用 RewriteCond 在应用规则前检查当前状态,并使用 [L] 标志在匹配后停止处理。

# BAD: Creates an infinite loop
# (The rewritten URL "/new" matches "^(.*)$" again)
RewriteRule ^(.*)$ /new/$1 [R=301]

# GOOD: Use RewriteCond to prevent the loop
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/new/ [NC]
RewriteRule ^(.*)$ /new/$1 [R=301,L]

# GOOD: Another approach - check if already redirected
RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)$ /new/$1 [R=301,L]

错误的 RewriteBase

RewriteBase 定义目录级重写的基础 URL 路径。如果 .htaccess 位于子目录中,RewriteBase 必须匹配该路径。使用错误的值会导致规则生成不正确的 URL。

# If .htaccess is in the document root:
RewriteEngine On
RewriteBase /

# If .htaccess is in /blog/ subdirectory:
RewriteEngine On
RewriteBase /blog/

# If .htaccess is in /app/public/ subdirectory:
RewriteEngine On
RewriteBase /app/public/

# Common mistake: Using RewriteBase /blog when file is at root
# This causes all rewritten URLs to be prefixed with /blog

规则顺序很重要

Apache 从上到下处理 .htaccess 规则。如果通用规则出现在特定规则之前,它会先匹配,特定规则永远不会执行。始终将特定规则放在通用规则之前,并使用 [L] 标志防止进一步处理。

# BAD: General rule before specific rule
RewriteEngine On
RewriteRule ^(.*)$ /index.php?page=$1 [L]        # Catches everything!
RewriteRule ^about$ /about-us.html [R=301,L]      # Never reached!

# GOOD: Specific rules first, general rules last
RewriteEngine On
RewriteRule ^about$ /about-us.html [R=301,L]      # Specific: runs first
RewriteRule ^contact$ /contact-us.html [R=301,L]  # Specific: runs second
RewriteCond %{REQUEST_FILENAME} !-f                # Skip existing files
RewriteCond %{REQUEST_FILENAME} !-d                # Skip existing dirs
RewriteRule ^(.*)$ /index.php?page=$1 [L]          # General: fallback
错误修复方法
缺少 RewriteEngine On始终在重写规则块顶部添加 "RewriteEngine On"
模式中未转义点号在正则模式中使用 \. 而不是 .(点号匹配任意字符)
忘记 [L] 标志添加 [L] 在匹配后停止规则处理,防止级联问题
混用 Redirect 和 RewriteRule坚持使用一种方法;混用会导致不可预测的行为
未清除浏览器缓存测试301 重定向会被浏览器缓存;测试时使用 302,生产环境再改为 301
.htaccess 文件权限错误设置权限为 644(所有者读写,组/其他人只读)

常见问题

什么是 .htaccess?应该放在哪里?

.htaccess(超文本访问)是 Apache Web 服务器的分布式配置文件。将其放在网站根目录(通常是 public_html 或 www)。它影响所在目录及所有子目录。您也可以在子目录中放置额外的 .htaccess 文件来覆盖父级规则。文件必须命名为 ".htaccess",包含前导点号。

301 和 302 重定向有什么区别?

301 重定向是永久性的——它告诉搜索引擎将所有链接权重(SEO 价值)传递到新 URL 并更新索引。302 重定向是临时性的——搜索引擎保留原始 URL。永久移动(域名更改、URL 重组)使用 301,临时情况(A/B 测试、维护页面)使用 302。浏览器会积极缓存 301 重定向,因此测试时使用 302。

为什么我的 .htaccess 规则不起作用?

最常见的原因:1)mod_rewrite 未启用——运行 "a2enmod rewrite" 并重启 Apache;2)Apache 配置中 AllowOverride 设置为 None——改为 "AllowOverride All";3).htaccess 文件权限不正确(应为 644);4)语法错误——检查 Apache 错误日志;5)浏览器缓存了之前的 301 重定向——清除缓存或使用隐身模式测试。

.htaccess 能在 Nginx 上使用吗?

不能,.htaccess 是 Apache Web 服务器特有的。Nginx 不支持 .htaccess 文件。如果使用 Nginx,需要将等效指令直接添加到 Nginx 服务器块配置中。有在线工具可以帮助将常见 .htaccess 规则转换为 Nginx 配置语法,但转换并非完全一一对应。

网站改版后如何重定向旧 URL?

创建旧 URL 到新 URL 的映射,为每个添加 Redirect 或 RewriteRule。对于大规模更改,使用 RewriteMap 和外部文件。对于基于模式的更改(如 /blog/post-name 到 /articles/post-name),使用带正则捕获组的 RewriteRule:RewriteRule ^blog/(.*)$ /articles/$1 [R=301,L]。始终使用 curl -I 测试重定向以验证状态码和目标。

.htaccess 如何影响网站性能?

Apache 在每次请求时都会读取 .htaccess 文件,这增加了少量性能开销。对于高流量网站,最好将规则移至 Apache 主配置(httpd.conf 或虚拟主机文件),并将 AllowOverride 设为 None。但对于大多数网站,性能影响可以忽略不计。.htaccess 的便利性(无需重启服务器、适用于共享主机)远大于最小的性能成本。

本 .htaccess 速查表涵盖了最基本的重定向模式、安全配置和性能优化。始终使用 curl 或在线重定向检查器彻底测试更改,并在部署到生产环境之前备份可用的 .htaccess 文件。

𝕏 Twitterin LinkedIn
这篇文章有帮助吗?

保持更新

获取每周开发技巧和新工具通知。

无垃圾邮件,随时退订。

试试这些相关工具

.ht.htaccess GeneratorNXNginx Config Generator%20URL Encoder/Decoder🤖Robots.txt Generator

相关文章

Nginx 配置示例:反向代理、SSL 和静态站点

生产级 Nginx 配置示例:反向代理、SSL/TLS、静态文件服务、负载均衡和安全头。

内容安全策略 (CSP) 完全指南:从基础到生产部署

从零学习 CSP:所有指令、常见配置、报告机制和分步部署指南。