为什么Apache Permanent Redirect会删除域和路径之间的斜杠?

Nat*_*man 18 apache .htaccess mod-rewrite https redirect

我正在使用Apache 2.4,我设置了两个虚拟目录.一个需要SSL,另一个重定向到它.

如果用户尝试在https://www.derp.com/derp没有/ derp存在的情况下访问,则会正确获取404.但是当用户访问时http://www.derp.com/derp,Apache会错误地将用户重定向到https://www.derp.comderp,删除路径和域名之间的斜杠.

我不知道是什么原因引起的.

以下是我的虚拟主机的设置.

<VirtualHost *:443>
    ServerAdmin derp@derp.com
    ServerName www.derp.com
    ServerAlias derp.com
    DocumentRoot "C:\Users\derp\Documents\Web Projects\derp"
    SSLEngine on
    SSLCertificateFile "C:\Apache24\certs\cert.cer"
    SSLCertificateKeyFile "C:\Apache24\certs\key.key"
</VirtualHost>

<VirtualHost *:80>
    ServerAdmin derp@derp.com
    ServerName www.derp.com
    ServerAlias derp.com
    Redirect permanent / https://www.derp.com/
</VirtualHost>

<Directory "C:\Users\derp\Documents\Web Projects\derp">
    Options Indexes FollowSymLinks Includes ExecCGI
    AllowOverride All
    Require all granted
    SSLRequireSSL
</Directory>
Run Code Online (Sandbox Code Playgroud)

为什么Apache会这样表现?

红利问题:重定向应该在我的虚拟主机定义中处理,还是应该在网站的物理目录中的.htaccess文件中处理?


编辑:

我正在启动一个Laravel项目,默认情况下公用文件夹确实包含.htaccess文件,所以这是那个人:

<IfModule mod_rewrite.c>
    Options -MultiViews
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>
Run Code Online (Sandbox Code Playgroud)

编辑二:

我试过了:

  • 在DirectoryRoot路径的末尾添加斜杠
  • 用DirectoryRoot路径中的正斜杠替换反斜杠
  • 在DirectoryRoot路径中用双反斜杠替换反斜杠

我还完全从目录中删除了.htaccess文件.

当你从它去正确地重定向http://www.derp.comhttps://www.derp.com.只是当您指定路径并尝试https时,它会删除域和路径之间的斜杠.


编辑三:

我还尝试了以下建议:

Redirect permanent / https://www.derp.com/

Try

RedirectMatch permanent /(.*) https://www.derp.com/$1

or

RedirectMatch permanent (.*) https://www.derp.com/$1
Run Code Online (Sandbox Code Playgroud)

...而不是重定向到https://www.derp.comderp,而不是重定向,尝试并为http://www.derp.com/derp提供404 ,但使用Apache的404,而不是投掷一个未找到的例外,因为Laravel没有配置.


编辑四:

我也尝试过:

<IfModule mod_rewrite.c>
    Options -MultiViews
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.php$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.php [L]
</IfModule>
Run Code Online (Sandbox Code Playgroud)

在.htaccess文件中,行为根本没有改变.

Kev*_*han 7

我的问题与浏览器缓存有关。

我在不同的浏览器中尝试过,它可以工作,然后在第一个浏览器的私人会话中再次尝试,它也可以工作。


Nat*_*man 5

我知道了.

问题根本不在于重写,而是我的Directory定义下的SSLRequireSSL指令导致了问题.

我只是删除了这个指令,刷新了我所有浏览器中的缓存,然后该网站继续正常工作.这是通过消除过程发现的.

文档说明:

除非为当前连接启用HTTP over SSL(即HTTPS),否则此指令禁止访问.这在启用SSL的虚拟主机或目录中非常方便,可以防止暴露应该受保护的内容的配置错误.如果存在此指令,则拒绝所有未使用SSL的请求.

重点是我自己的.如果未启用HTTP over SSL,SSLRequireSSL可能只让Apache返回403或404,从而干扰重写规则.根据您的使用情况,重写规则(例如服务器故障的答案中的重写规则)可能是更好的选择:

RewriteEngine On
RewriteCond %{SERVER_PORT} !443
RewriteRule ^(/(.*))?$ https://%{HTTP_HOST}/$1 [R=301,L]
Run Code Online (Sandbox Code Playgroud)