Apache URL重写与重定向

Apache URL Rewriting and Redirection

概述 (Overview)

URL重写和重定向是Web服务器的重要功能,能够改善用户体验、优化SEO、实现旧URL兼容和安全控制。本文将详细介绍Apache中mod_rewrite模块的使用方法,包括重写规则语法、条件匹配、重定向技术等核心技术。

URL rewriting and redirection are important web server features that can improve user experience, optimize SEO, implement old URL compatibility, and security control. This article will detail the use of Apache's mod_rewrite module, including rewrite rule syntax, conditional matching, redirection techniques, and other core technologies.

1. mod_rewrite基础配置 (mod_rewrite Basic Configuration)

1.1 启用mod_rewrite模块 (Enabling mod_rewrite Module)

# 启用重写模块
sudo a2enmod rewrite

# 重启Apache
sudo systemctl restart apache2

# 验证模块是否启用
apache2ctl -M | grep rewrite

1.2 基本重写规则配置 (Basic Rewrite Rule Configuration)

# 启用重写引擎
RewriteEngine On

# 基本重写规则
RewriteRule ^old-page\.html$ /new-page.html [R=301,L]

# 重写到内部路径
RewriteRule ^products/([0-9]+)/?$ /product.php?id=$1 [L]

# 重定向到外部URL
RewriteRule ^external-link/?$ https://www.example.com/ [R=302,L]

2. 重写规则语法 (Rewrite Rule Syntax)

2.1 RewriteRule基本语法 (RewriteRule Basic Syntax)

# RewriteRule语法
RewriteRule Pattern Substitution [Flags]

# 示例
RewriteRule ^article/([0-9]+)/?$ /view.php?id=$1 [L]

2.2 常用重写标志 (Common Rewrite Flags)

# 常用标志说明
# [L] - Last rule, stop processing
# [R] - Redirect (302 by default)
# [R=301] - Permanent redirect
# [R=302] - Temporary redirect
# [N] - Next pass, re-run rules
# [S=x] - Skip next x rules
# [E=VAR:VAL] - Set environment variable
# [F] - Forbidden (403)
# [G] - Gone (410)
# [H=Content-Type] - Set content type
# [T=Content-Type] - Set content type
# [QSA] - Query string append
# [QSD] - Query string discard
# [B] - Escape backreferences

2.3 正则表达式模式 (Regular Expression Patterns)

# 常用正则表达式模式
^              # 行开始
$              # 行结束
.              # 任意字符
.*             # 任意字符0次或多次
.+             # 任意字符1次或多次
?              # 前面的字符0次或1次
[0-9]+         # 数字1次或多次
[a-zA-Z]+      # 字母1次或多次
([0-9]+)       # 捕获数字组
([^/]+)        # 捕获非斜杠字符组

3. 条件重写 (Conditional Rewriting)

3.1 RewriteCond基本用法 (RewriteCond Basic Usage)

# 基本条件重写
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]

# 多条件重写
RewriteCond %{HTTP_HOST} ^oldsite\.com$ [NC]
RewriteCond %{REQUEST_URI} ^/old-page\.html$
RewriteRule ^(.*)$ https://newsite.com/new-page.html [R=301,L]

3.2 常用条件变量 (Common Condition Variables)

# 常用条件变量
%{HTTP_HOST}           # 主机头
%{REQUEST_URI}         # 请求URI
%{QUERY_STRING}        # 查询字符串
%{HTTP_USER_AGENT}     # 用户代理
%{HTTP_REFERER}        # 引荐页面
%{REMOTE_ADDR}         # 客户端IP
%{HTTPS}               # HTTPS状态
%{SERVER_PORT}         # 服务器端口
%{REQUEST_METHOD}      # 请求方法
%{THE_REQUEST}         # 原始请求行
%{HTTP_COOKIE}         # Cookie头

3.3 复杂条件重写 (Complex Conditional Rewriting)

# 基于用户代理的重写
RewriteCond %{HTTP_USER_AGENT} ^.*(Mobile|Android|iPhone).*$ [NC]
RewriteRule ^(.*)$ /mobile/$1 [L]

# 基于IP的重写
RewriteCond %{REMOTE_ADDR} ^192\.168\.1\.
RewriteRule ^admin/?$ /admin-panel/ [L]

# 基于时间的重写
RewriteCond %{TIME_HOUR}%{TIME_MIN} >0800
RewriteCond %{TIME_HOUR}%{TIME_MIN} <1800
RewriteRule ^contact/?$ /contact-form/ [L]

# 基于查询字符串的重写
RewriteCond %{QUERY_STRING} ^id=([0-9]+)
RewriteRule ^old-page\.php$ /new-page/%1? [R=301,L]

4. URL重定向技术 (URL Redirection Techniques)

4.1 永久重定向 (Permanent Redirect)

# 301永久重定向
RewriteRule ^old-page\.html$ /new-page.html [R=301,L]

# 重定向整个域名
RewriteCond %{HTTP_HOST} ^old-domain\.com$ [NC]
RewriteRule ^(.*)$ https://new-domain.com/$1 [R=301,L]

# 重定向HTTP到HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

4.2 临时重定向 (Temporary Redirect)

# 302临时重定向
RewriteRule ^temp-page\.html$ /maintenance.html [R=302,L]

# 基于条件的临时重定向
RewriteCond %{HTTP_USER_AGENT} ^.*bot.*$ [NC]
RewriteRule ^special-content/?$ /bot-content/ [R=302,L]

4.3 特殊重定向 (Special Redirects)

# 403禁止访问
RewriteRule ^private/?$ - [F,L]

# 410内容已删除
RewriteRule ^deleted-page\.html$ - [G,L]

# 自定义重定向状态码
RewriteRule ^custom-redirect/?$ /target-page/ [R=307,L]

5. SEO优化重写 (SEO Optimization Rewriting)

5.1 友好URL重写 (Friendly URL Rewriting)

# 将动态URL重写为友好URL
RewriteRule ^product/([0-9]+)/?$ /product.php?id=$1 [L]
RewriteRule ^category/([^/]+)/?$ /category.php?name=$1 [L]
RewriteRule ^user/([^/]+)/?$ /profile.php?username=$1 [L]

# 分页URL重写
RewriteRule ^articles/page/([0-9]+)/?$ /articles.php?page=$1 [L]

# 搜索URL重写
RewriteRule ^search/([^/]+)/?$ /search.php?q=$1 [L]

5.2 多语言URL重写 (Multi-language URL Rewriting)

# 多语言URL重写
RewriteRule ^en/(.*)$ /index.php?lang=en&$1 [L]
RewriteRule ^zh/(.*)$ /index.php?lang=zh&$1 [L]
RewriteRule ^es/(.*)$ /index.php?lang=es&$1 [L]

# 基于Accept-Language头的重写
RewriteCond %{HTTP:Accept-Language} ^en [NC]
RewriteRule ^$ /en/ [L]

RewriteCond %{HTTP:Accept-Language} ^zh [NC]
RewriteRule ^$ /zh/ [L]

6.1 防止恶意访问 (Preventing Malicious Access)

# 阻止可疑的查询字符串
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
RewriteRule ^(.*)$ index.php [F,L]

# 阻止访问敏感文件
RewriteRule ^(.*)\.log$ - [F,L]
RewriteRule ^(.*)\.conf$ - [F,L]
RewriteRule ^(.*)\.bak$ - [F,L]

# 限制请求方法
RewriteCond %{REQUEST_METHOD} !^(GET|POST|HEAD)$
RewriteRule ^(.*)$ - [F,L]

6.2 防止热链接 (Preventing Hotlinking)

# 防止图片热链接
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?example\.com [NC]
RewriteRule \.(jpg|jpeg|png|gif|bmp)$ - [F,NC,L]

# 替换热链接图片
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?example\.com [NC]
RewriteRule \.(jpg|jpeg|png|gif)$ /images/hotlink-denied.png [R,L]

7. 高级重写技术 (Advanced Rewriting Techniques)

7.1 虚拟主机重写 (Virtual Host Rewriting)

<VirtualHost *:80>
    ServerName www.example.com

    RewriteEngine On

    # 虚拟主机特定重写规则
    RewriteRule ^api/v1/(.*)$ /api/v2/$1 [R=301,L]

    # 基于路径的重写
    RewriteRule ^legacy/(.*)$ /modern/$1 [L]
</VirtualHost>

7.2 动态重写 (Dynamic Rewriting)

# 基于数据库的动态重写
RewriteMap dbmap "txt:/etc/apache2/rewrite-map.txt"
RewriteRule ^/old/([^/]+)$ /new/${dbmap:$1|notfound} [L]

# 基于程序的动态重写
RewriteMap prgmap "prg:/usr/local/bin/rewrite-script.pl"
RewriteRule ^/dynamic/(.*)$ /static/${prgmap:$1} [L]

8. 调试和故障排除 (Debugging and Troubleshooting)

8.1 重写日志配置 (Rewrite Log Configuration)

# 启用重写日志(Apache 2.2及更早版本)
# RewriteLog /var/log/apache2/rewrite.log
# RewriteLogLevel 3

# Apache 2.4中的调试方法
LogLevel alert rewrite:trace3

# 或者更详细的日志
LogLevel debug rewrite:trace8

8.2 重写测试脚本 (Rewrite Test Script)

#!/bin/bash
# rewrite-test.sh

test_rewrite() {
    local url=${1:-"http://localhost/test"}

    echo "=== Rewrite Test ==="
    echo "Testing URL: $url"
    echo

    # 测试重写结果
    echo "1. HTTP Response:"
    curl -I -s "$url" | grep -E "HTTP|Location"

    echo
    echo "2. Final URL:"
    curl -s -L --max-redirs 0 -o /dev/null -w "%{url_effective}\n" "$url"

    echo
    echo "3. All Redirects:"
    curl -s -L -D - "$url" | grep -E "HTTP|Location" | head -10

    echo
    echo "Test completed!"
}

test_rewrite $1

8.3 常见问题解决 (Common Problem Solutions)

# 1. 解决循环重写问题
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)$ /index.php [L]

# 2. 保留查询字符串
RewriteRule ^old-page/?$ /new-page/ [QSA,L]

# 3. 丢弃查询字符串
RewriteRule ^old-page/?$ /new-page/ [QSD,L]

# 4. 处理尾部斜杠
RewriteRule ^(.+)/$ /$1 [R=301,L]

小结 (Summary)

通过本文学习,你应该掌握:

  1. Apache mod_rewrite模块的启用和基本配置
  2. 重写规则语法和常用标志
  3. 条件重写和正则表达式模式
  4. URL重定向技术(301、302等)
  5. SEO优化的URL重写方法
  6. 安全相关的重写规则
  7. 高级重写技术和动态重写
  8. 重写调试和故障排除方法

URL重写和重定向是Web开发中的重要技能,正确使用这些技术能够显著改善用户体验和SEO效果。在下一篇文章中,我们将详细介绍Apache缓存配置与优化技术。

powered by Gitbook© 2025 编外计划 | 最后修改: 2025-08-29 15:40:15

results matching ""

    No results matching ""