【问题标题】:Mod-Rewrites Not Working in htaccess with PHPMod-Rewrites 在 PHP 的 htaccess 中不起作用
【发布时间】:2021-02-12 07:33:02
【问题描述】:

我已经从我的其他站点复制了 htaccess 文件(所有站点都可以工作,并且在同一台服务器上)并且只更改了需要更改的 URL(即从非 www 重定向到 www 时),但它根本没有工作。

例如,我将 /index.php 更改为 /index 失败,但 /example.html 确实在 /example 工作,这让我认为这是 PHP 或 htaccess 与 PHP 一起工作的问题?

我已经让我的几个朋友看了一下,他们不明白为什么会这样。

我的 .htaccess 文件是:

RewriteEngine On

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

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [NC,L] 

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.*)$ $1.html [NC,L] 

我的虚拟主机是:

<VirtualHost *:443>
  ServerName example.com
  ServerAlias localhost
  DocumentRoot "/var/www/example.com/public_html"
  <Directory "/var/www/example.com/public_html">
    Options +Includes +FollowSymLinks +MultiViews
    AllowOverride All
    Require all granted
  </Directory>
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>

<VirtualHost *:80>
  ServerName example.com
  ServerAlias localhost
  DocumentRoot "/var/www/example.com/public_html"
  <Directory "/var/www/example.com/public_html">
    Options +Includes +FollowSymLinks +MultiViews
    AllowOverride All
    Require all granted
  </Directory>
RewriteEngine on
RewriteCond %{SERVER_NAME} =example.com [OR]
RewriteCond %{SERVER_NAME} =localhost
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

<VirtualHost *:443>
  ServerName www.example.com
  ServerAlias localhost
  DocumentRoot "/var/www/example.com/public_html"
  <Directory "/var/www/example.com/public_html">
    Options +Indexes +Includes +FollowSymLinks +MultiViews
    AllowOverride All
    Require all granted
  </Directory>
SSLCertificateFile /etc/letsencrypt/live/www.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>

<VirtualHost *:80>
  ServerName www.example.com
  ServerAlias localhost
  DocumentRoot "/var/www/example.com/public_html"
  <Directory "/var/www/example.com/public_html">
    Options +Indexes +Includes +FollowSymLinks +MultiViews
    AllowOverride All
    Require all granted
  </Directory>
RewriteEngine on
RewriteCond %{SERVER_NAME} =www.example.com [OR]
RewriteCond %{SERVER_NAME} =localhost
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

(我已经用 example.com 替换了域——它们与 htaccess 或 vhost 中的不同。)

.htaccess 当然没有被禁用,如果我进行重定向它就可以正常工作,例如:

Redirect 301 /test https://example.com/test

还有……

root@server:~# a2enmod rewrite
Module rewrite already enabled

我以前从未在我的网络服务器上遇到过任何类似的问题,我真的很困惑为什么会出现这个问题。

【问题讨论】:

    标签: php apache .htaccess mod-rewrite virtualhost


    【解决方案1】:

    您实际上并没有说明发生了什么(错误?响应代码?等),但是,您的配置存在一些与无扩展 URL 相关的问题。

    Options +Indexes +Includes +FollowSymLinks +MultiViews
    

    您在服务器配置中明确启用MultiViews,但是,这将与尝试附加文件扩展名的.htaccess 中的mod_rewrite 指令冲突。 MultiViews 需要禁用。例如。 -MultiViews(不是+)。

    但是,出于某种原因,您还启用了目录索引 (Indexes) 和服务器端包含 (Includes)?这是故意的吗?而且,相当令人困惑的是,您为 www 子域设置了与域顶点不同的选项?

    在 vHost 容器中,通常最好只说明所需的选项。例如:

    Options FollowSymLinks
    

    (这自然会通过不设置多视图来禁用它。)

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME}\.php -f
    RewriteRule ^(.*)$ $1.php [NC,L]
    

    .htaccess 中这些用于附加文件扩展名的 mod_rewrite 指令并不完全正确。虽然它们可能适用于您的“有效” URL,但恶意用户可以构造一个 /index/&lt;anything&gt; 形式的 URL,否则将映射到 /index.php,以触发重写循环(500 内部服务器错误)*1.

    这些应该写成这样(假设您的.htaccess 文件位于文档根目录中)以避免此漏洞:

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{DOCUMENT_ROOT}/$1.php -f
    RewriteRule (.*) $1.php [L]
    
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{DOCUMENT_ROOT}/$1.html -f
    RewriteRule (.*) $1.html [L]
    

    文字点不需要在 TestStringRewriteCond 指令的第一个参数)中转义,因为这是一个“字符串”,而不是正则表达式。此处不需要NC 标志。

    如果您的 URL 本身不包含“文件扩展名”,那么您可以通过不测试已经看起来像它们具有文件扩展名的 URL 来优化上述内容。例如:

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.php -f
    RewriteRule !\.\w{2,4}$ %{REQUEST_URI}.php [L]
    

    否定 正则表达式 !\.\w{2,4}$ 仅匹配不包含文件扩展名的 URL - 看起来像 - 文件扩展名。在这种情况下,文件扩展名是 URL 路径末尾的 2 到 4 个字母/数字的序列,前面有一个点。


    *1请参阅my answer 了解以下 ServerFault 问题,该问题更详细地介绍了潜在的重写循环和导致的 500 错误响应:

    【讨论】:

      猜你喜欢
      • 2015-10-28
      • 1970-01-01
      • 1970-01-01
      • 2012-07-21
      • 1970-01-01
      • 2010-10-28
      • 1970-01-01
      • 1970-01-01
      • 2012-09-11
      相关资源
      最近更新 更多