【问题标题】:Customize URL rewriting with htaccess使用 htaccess 自定义 URL 重写
【发布时间】:2020-10-01 22:05:01
【问题描述】:

我的 htaccess 中有以下内容:

RewriteEngine On
RewriteRule ^reset-password/?$ /pwreset.php [NC,L]

完美运行,问题是直接访问PHP文件时是否也可以自动重定向到新路径?

例如:example.com/pwreset.php >> example.com/reset-password

有好几页,所以我需要一些实用的东西。

更新:

RewriteRule .* - [E=URL:https://user.example.com]
RewriteRule ^pwreset\.php$ %{ENV:URL}/reset-password [R=301,L]
RewriteRule ^reset-password$ pwreset.php [END]
RewriteRule ^clientarea\.php$ %{ENV:URL}/home [R=301,L]
RewriteRule ^home$ clientarea.php [END]
RewriteRule ^logout\.php$ %{ENV:URL}/logout [R=301,L]
RewriteRule ^logout$ logout.php [END]

困难在于这样的链接:user.example.com/clientarea.php?action=services

访问时会重定向到:user.example.com/home?action=services

我需要在这些链接的情况下重定向到:user.example.com/services

你能帮我解决这个新规则吗?以及如何简化这一切。

【问题讨论】:

    标签: php .htaccess mod-rewrite


    【解决方案1】:

    要将/pwreset.php 的直接请求从外部重定向到/reset-password,您可以在现有的内部重写之前执行以下操作:

    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteRule ^pwreset\.php$ /reset-password [R=301,L]
    

    为了避免重定向循环,检查REDIRECT_STATUS env var 的条件是必要的,因为我们只想重定向用户发出的直接请求,而不是其他指令重写的请求。 REDIRECT_STATUS 在初始请求中为空,并在第一次成功重写后设置为“200”(如 200 OK)。

    首先使用 302(临时)重定向进行测试以避免潜在的缓存问题。


    UPDATE#1:有没有办法把它放在同一个规则中?因为页面很多,所以我实际上必须复制每一行。

    不,如果您使用单个 .htaccess 文件并且您想通过 .htaccess 执行所有操作,那么您需要为每个外部重定向重复两个指令(RewriteCondRewriteRule)。如果没有RewriteCond 指令(条件),重写的请求也会被重定向——创建一个无限循环。

    但是,您可以在子目录中使用第二个.htaccess 文件来处理重定向。这将避免每个规则的附加条件。

    例如,不是如上所述重定向pwreset.php。您可以在内部重写.php 文件的所有请求(假设您没有直接访问任何 .php 文件)到包含另一个.htaccess 的子目录,其中包含必要的重定向。

    1. 将上面的重定向改成表单的重写:

      # Rewrite all direct requests for `.php` files to a subdirectory
      RewriteCond %{ENV:REDIRECT_STATUS} ^$
      RewriteRule (.+\.php)$ /redirect-handler/$1 [L]
      

      其中/redirect-handler 是一个物理子目录。

    2. 使用必要的重定向创建/redirect-handler/.htaccess

      # Redirect direct requests for .php files to the canonical URL.
      # If we are here then we know that the .php file has been called directly
      # so do not need an additional condition before each rule.
      
      RewriteEngine On
      
      RewriteRule ^pwreset\.php$ /reset-password [R=301,L]
      RewriteRule ^another\.php$ /canonical-url [R=301,L]
      

    另一种选择是将请求重写为 PHP 脚本,而不是包含另一个 .htaccess 文件的子目录,而是在 PHP 中执行重定向。

    例如,您最初的“重定向”变为:

    # Rewrite all direct requests for `.php` files to PHP script
    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteCond %{REQUEST_URI} !^/redirect-handler\.php$
    RewriteRule (.+\.php)$ /redirect-handler.php?url=$1 [L]
    

    然后,在/redirect-handler.php 中,您将检查$_GET['url'] var 以获取所请求的PHP 文件。 (或者只检查$_SERVER['REQUEST_URI'] 超全局。)查找所需的规范 URL,如果请求映射到有效 URL,则 301“重定向”或返回 404。

    您可以更进一步,在 PHP 中管理所有内容 - 在单个脚本中。这有一个明显的优势,即您只有一个包含 PHP 文件/canonical-url 映射的列表(PHP assoc 数组或 DB 表)。除了.htaccess 中的初始重写之外,在添加/删除/更新 URL 时,您不需要更新 .htaccess。尽管您可能需要修改现有页面,具体取决于您包含文件等的方式(?)


    UPDATE#2:使用单个 .htaccess 文件...如果您使用的是 Apache 2.4(而不是 2.2),那么您可以在内部重写时使用 END 标志(而不是 L 标志),这将避免在“重定向”上指定附加条件(RewriteCond 指令)。

    例如:

    RewriteEngine On
    
    # Canonical redirects...
    RewriteRule ^pwreset\.php$ /reset-password [R=301,L]
    :
    
    # Internal rewrites...
    RewriteRule ^reset-password$ pwreset.php [END]
    :
    

    L 标志不同,END 标志停止所有处理,从而防止重写引擎重新启动。

    请注意,我对您最初的重写做了一些小改动...

    • 删除了NC 标志 - 你真的需要不区分大小写的匹配吗?否则,这可能会导致内容重复问题,但您应该始终链接到单个规范 URL。
    • 删除了RewriteRule 模式上的可选斜杠。 (原因同上。)
    • 删除了RewriteRule substitution 字符串上的斜杠前缀 - 它不是必需的并且简化了重写(它现在重写为文件系统路径 - 这就是它的本质 - 而不是 URL 路径)。

    这比上面列出的方法要简单得多! (尽管这些方法仍然有其用途。)

    【讨论】:

    • 太酷了,有没有办法把它放在同一个规则中?因为页面很多,所以我实际上必须复制每一行。
    • 不,通常您需要为每个重定向重复这两个指令。但是,您可以稍微改变您的方法并使用另一个 .htaccess 文件,甚至可以在 PHP 中执行所有操作。我已经更新了我的答案。
    • 谢谢!我有两个问题,链接没有子目录,我无权访问 php 文件,因为它们是加密的。只在主目录的 htaccess 文件中重复会怎样?
    • 这个想法只是改变访问链接的文字,它并不是一个目录。也就是说,我只希望example.com/reset-password 可以访问example.com/pwreset.php URL。
    • 如果您使用的是 Apache 2.4,那么您实际上可以使用 END 标志来避免额外的指令。 (对不起,我之前忽略了这一点 - 这让事情变得更容易!)我已经更新了我的答案。为了澄清......“链接没有子目录” - 没关系。链接是否有子目录在这里并不重要。 “这个想法只是更改访问链接的文字” - 我假设您已经更改了 HTML 源代码中的实际链接? (尽管如果您无权访问 PHP 代码,那么可能没有?!)您仍然必须更改 HTML 源代码中的 URL。
    猜你喜欢
    • 2016-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多