Apache mod_alias RedirectMatch 除特定模式外的所有内容

Posted

技术标签:

【中文标题】Apache mod_alias RedirectMatch 除特定模式外的所有内容【英文标题】:Apache mod_alias RedirectMatch everything except specific pattern 【发布时间】:2014-12-11 13:12:00 【问题描述】:

好旧的正则表达式快把我逼疯了。

我需要使用 Redirect from mod_alias(不能使用 mod_rewrite)将 Apache 2.4 中的所有流量从 HTTP 重定向到 HTTPS,“/bt/sub/[a_few_endings]”除外。

我在我认识的所有在线测试人员(例如http://regex101.com/)中测试了以下正则表达式,并且所有人都确认该正则表达式确实应该匹配除我不希望它匹配的 URL 之外的所有内容:

^/(?!bt/sub/(went_active|success|cancel|expired)).*$ 

据我所知,这应该匹配 http://local.mysite.com 中的 everything 并将其重定向到 https ://local.mysite.com,除了为以下四种:

http://local.mysite.com/bt/sub/went_active http://local.mysite.com/bt/sub/success http://local.mysite.com/bt/sub/cancel http://local.mysite.com/bt/sub/expired

不过,Apache 会重定向所有内容,包括上述我不想重定向的 URL。

我在 SO 中发现了几个类似的问题,但大多数问题都是根据 mod_rewrite 来回答的,这不是我想要/需要的,而且人们说有用的那些对我没有用。

这是我目前的虚拟主机配置:

<VirtualHost *:80> 
    ServerName local.mysite.com 
    RedirectMatch 302 ^/(?!bt/sub/(went_active|success|cancel|expired)).*$ https://local.mysite.com 
    DocumentRoot /home/borfast/projects/www/mysite/public 
    #Header set Access-Control-Allow-Origin * 
    SetEnv LARAVEL_ENV localdev 

    <Directory /home/borfast/projects/www/mysite/public/> 
        Options All 
        DirectoryIndex index.php 
        AllowOverride All 
        Require all granted 
    </Directory> 
</VirtualHost>

请帮助并防止我发疯:)


更新: 发生了一些奇怪的事情:显然,当可以找到请求的 URL/路径时,Apache 会忽略 RedirectMatch 中的表达式并重定向客户端,即使 RedirectMatch 告诉它不要这样做。

为了测试这一点,我在一个单独的虚拟机中从头开始创建了一个新的虚拟主机,该虚拟机新安装了 Ubuntu Trussty 64,加载了 Apache 2.4。这个新的虚拟主机只包含 ServerName、RedirectMatch 和 DocumentRoot 指令,如下所示:

<VirtualHost *:80>
    ServerName testing.com
    RedirectMatch 302 ^/(?!bt/sub/(went_active|success)$).*$ https://othersite.com/

    DocumentRoot /home/vagrant/www
</VirtualHost>

我创建了目录/home/vagrant/www/bt/sub/went_active 以确保 Apache 至少可以访问两个可能的 URL 之一。在尝试访问 http://testing.com:8080 时,我按预期被重定向。

然后奇怪的是:访问http://testing.com:8080/bt/sub/went_active时,与我创建的目录匹配的URL,我仍然被重定向,即使我不应该,但是当访问http://testing.com:8080/bt/sub/success时,我没有被重定向并且而是获得 403 Forbidden。

我可能对此失去了理智,但似乎当 Apache 发现它可以为请求提供服务并且它与 RedirectMatch 中应该阻止重定向的正则表达式匹配时,它决定忽略正则表达式并进行重定向.三个字母:WTF?!?!?!

【问题讨论】:

你的正则表达式匹配我的所有内容.*\.com\/foo\/bar\/(aaa|bbb|ccc|ddd) 我做了这个只匹配您不想替换的那些,如果您无法在代码中执行逻辑并需要它来匹配对立,只需将其设置为负前瞻或其他方式 无需转义/ 更容易使用mod_rewrite ... 是的,但我明确表示我需要使用 mod_alias。如果人们不每年都买一部新手机,世界会更好,除此之外,还有很多事情是你无法改变的。 ;) 【参考方案1】:

正如在 cmets 中所说 - 使用 mod_rewrite 更容易。可能的解决方案

RewriteEngine On
RewriteCond %REQUEST_URI !^/bar/(abcd|baz|barista|yo)$ [NC]
RewriteRule ^ http://site/ [R=301,L]

另一个(对于 .htaccess,初始 / 已从 RewriteRule 中删除)

RewriteEngine On
RewriteRule !^bar/(abcd|baz|barista|yo)$ http://site/ [R=301,L,NC]

RedirectMatch的解决方案

RedirectMatch permanent ^(?!/bar/(abcd|baz|barista|yo)$).* http://site/

一切正常,您在测试/调试状态下可能遇到的问题是浏览器缓存了301 响应。因此,当您尝试检查或编写正确的代码时 - 使用 302 响应,而不是 301。如果不需要不区分大小写,请删除 NC 标志。

【讨论】:

我知道 mod_rewrite 会更容易,但我明确表示我需要使用 mod_alias。至于缓存,我考虑到这一点并尝试了几种不同的结尾(abcd、baz 等 - 每次都是新的),并监控 HTTP 请求以确保浏览器实际上获得了正确的重定向标头。 @borfast 我试过了,它可以工作(Ubuntu,Apache 2.4.7,都试过了)。这意味着您的问题不在这一行,而是在其他地方。没有足够的信息来准确判断它可能在哪里。 这几乎也是我要得出的结论。我刚刚用完整的虚拟主机配置更新了我的问题,以防有人可以在那里发现问题。 @borfast 您是否尝试将RedirectMatch 放入Directory 中?或者,至少在DocumentRoot 之后(不确定这是否重要,但更糟糕的是尝试)。我使用了.htaccess,但也可以尝试在配置中进行测试。 以前没试过,现在才试,两种可能。甚至在另一个浏览器上尝试过。没有快乐。【参考方案2】:

见this one

^\/.*(?&lt;!foo\/bar\/(aaa|bbb|ccc|ddd))$

匹配 / 后跟任何内容,除非字符串的结尾是 /foo/bar/(aaaa|bbb...)

(?&lt;! 是附加到字符串结尾 $ 的负向后视,它将检查它不可能匹配字符串结尾之前的内容。

如果您的真实案例不像您的示例那样静态,请为查询部分提供真实数据。

【讨论】:

Negative lookbehind 也应该起作用,并且也得到了在线正则表达式检查器的确认,但可惜,它不起作用。更具体地说,使用虚拟主机配置文件中的这一行:RedirectMatch 302 ^\/.*(?&lt;!foo\/bar\/(aaa|bbb|ccc|ddd))$ https ://mysite.com,我仍然会为每个 URL 重定向,包括 http://mysite.com/foo/bar/aaa(以及其他三个终止)。我的案例就是我描述的这个简单的案例。我希望每个 URL 都重定向到 HTTPS URL,除了这四个。不涉及查询,只是简单的 URL。起初看起来很简单......:| 我可能错了,但配置中还有其他涉及重定向的内容吗?我将不得不检查 apache 中的负前瞻和后视,您使用的是哪个版本? 糟糕,问题中的版本,我明天在 2.4 的 apache 上试试。 我不知道的有趣事实:lookbehinds 不适用于可变长度的交替。由于我的 URL 的结尾并不都具有相同的大小,因此向后查找可能不会奏效。该配置有一个ServerName、一个DocumentRoot 和一个SetEnv 指令,以及一个&lt;Directory&gt; 部分,仅此而已。我正在评论它们,看看它是否有所作为。 注释掉文件中的其他设置使其工作。不知道为什么,我正在一一尝试以确定是什么造成了不同。 ----- 编辑:没关系,虚惊一场,是我愚蠢。

以上是关于Apache mod_alias RedirectMatch 除特定模式外的所有内容的主要内容,如果未能解决你的问题,请参考以下文章

mod_rewrite 还是 mod_alias?

Apache 配置301跳转

apache常用模块介绍

apache_conf #redirect#301

apache_conf redirect.htaccess

apache_conf dev的redirect / uploads /文件夹