如何为启用友好网址的htaccess设置创建例外?

时间:2016-08-11 09:06:56

标签: apache .htaccess

我有一个LAMP服务器,但我做的网站编码和设计比Apache配置更多。我希望我的问题会很清楚,因为我不太了解.htaccess文件的语法,而且我的代码主要来源于网络上的教程。

我的网站使用“友好网址”,要启用该功能,我的.htaccess文件中包含以下代码:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.php

但是,我已经在一个子目录下创建了一个包含完整不同HTML的子目录,我希望能够通过这样的URL访问这个子目录:http://www.example.com/subdirectory

即使我直接转到http://www.example.com/subdirectory/index.html,Apache仍会重定向到根目录中的index.php

有没有办法可以修改我的.htaccess文件,以便我的subdirectory免于重定向?

更新: 经过一些实验,我已经确定正是这条线导致了这个问题(对于那些比我更熟练的人而言,这可能是显而易见的.htaccess文件):

RewriteRule ^(.*) index.php

如果我评论该行,那么子目录中的所有都可以正常工作(当然,网站的其余部分会中断)。如果我把它留在里面,我就会遇到上述问题。

正如下面的答案所示,我尝试将行改为:

RewriteRule !^subdirectory index.php

但这并没有解决问题。我还尝试在子目录中创建一个.htaccess文件,其中包含以下内容:

RewriteEngine On

不幸的是,这没有做任何事。

我对.htaccess语法的理解有限,说我已经拥有的行应该单独保留子目录的内容,但它的表现远比预期的要大得多。

有没有办法可以诊断和修复此行,以便它不会对我子目录的内容起作用?

更新2:

经过一些实验,我发现子目录中的.htaccess文件没有被读取。如果我在其中加入乱码文本,我不会收到任何错误,这似乎表明它甚至没有被访问。

我查找了为什么我的.htaccess文件可能无法被读取的原因,我发现在我的网站的.conf文件中,我需要这个代码:

AllowOverride All

我有那个指令,但子目录中的.htaccess仍未被读取。

我该怎么做以确保正在读取子目录中的.htaccess文件?

我的root .htaccess文件的内容:

# BEGIN Compress text files
<IfModule mod_deflate.c>
  <FilesMatch "\.(css|js|x?html?|php)$">
    SetOutputFilter DEFLATE
  </FilesMatch>
</IfModule>
# END Compress text files
# BEGIN Expire headers
<IfModule mod_expires.c>
  ExpiresActive On
  ExpiresDefault "access plus 1 seconds"
  ExpiresByType image/x-icon "access plus 2592000 seconds"
  ExpiresByType image/jpeg "access plus 2592000 seconds"
  ExpiresByType image/png "access plus 2592000 seconds"
  ExpiresByType image/gif "access plus 2592000 seconds"
  ExpiresByType application/x-shockwave-flash "access plus 2592000 seconds"
  ExpiresByType text/css "access plus 604800 seconds"
  ExpiresByType text/javascript "access plus 2592000 seconds"
  ExpiresByType application/javascript "access plus 2592000 seconds"
  ExpiresByType application/x-javascript "access plus 2592000 seconds"
  ExpiresByType text/html "access plus 600 seconds"
  ExpiresByType application/xhtml+xml "access plus 600 seconds"
</IfModule>
# END Expire headers
# BEGIN Cache-Control Headers
<IfModule mod_headers.c>
  <FilesMatch "\.(ico|jpe?g|png|gif|swf)$">
    Header set Cache-Control "max-age=2592000, public"
  </FilesMatch>
  <FilesMatch "\.(css)$">
    Header set Cache-Control "max-age=604800, public"
  </FilesMatch>
  <FilesMatch "\.(js)$">
    Header set Cache-Control "max-age=216000, private"
  </FilesMatch>
  <FilesMatch "\.(x?html?|php)$">
    Header set Cache-Control "max-age=600, private, must-revalidate"
  </FilesMatch>
</IfModule>
# END Cache-Control Headers
# BEGIN Turn ETags Off
<IfModule mod_headers.c>
  Header unset ETag
</IfModule>
FileETag None
# END Turn ETags Off
# BEGIN Remove Last-Modified Header
<IfModule mod_headers.c>
  Header unset Last-Modified
</IfModule>
# END Remove Last-Modified Header

# Make all requests pass through index.php to enable "friendly URLs"
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.php

# Turn off 'magic quotes'
php_value magic_quotes_gpc off

# Do not allow Perl script hackers, as they are probably just feeding useless Adsense "directory" sites
RewriteBase /
RewriteCond %{HTTP_USER_AGENT} libwww-perl.*
RewriteRule .* - [F,L]

# Filter for most common exploits
RewriteCond %{HTTP_USER_AGENT} libwww-perl [OR]
RewriteCond %{QUERY_STRING} tool25 [OR]
RewriteCond %{QUERY_STRING} cmd.txt [OR]
RewriteCond %{QUERY_STRING} cmd.gif [OR]
RewriteCond %{QUERY_STRING} r57shell [OR]
RewriteCond %{QUERY_STRING} c99 [OR]

# deny most common except .php
<FilesMatch "\.(inc|tpl|h|ihtml|sql|ini|conf|class|bin|spd|theme|module)$">
deny from all
</FilesMatch>

# Disable .htaccess viewing from browser
<Files ~ "^\.ht">
Order allow,deny
Deny from all
Satisfy All
</Files>

此代码位于我的/etc/apche2/apache2.conf

# Sets the default security model of the Apache2 HTTPD server. It does
# not allow access to the root filesystem outside of /usr/share and /var/www.
# The former is used by web applications packaged in Debian,
# the latter may be used for local directories served by the web server. If
# your system is serving content from a sub-directory in /srv you must allow
# access here, or in any related virtual host.
<Directory />
    Options FollowSymLinks
    AllowOverride None
    Require all denied
</Directory>

<Directory /usr/share>
    AllowOverride None
    Require all granted
</Directory>

<Directory /var/www/>
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

#<Directory /srv/>
#   Options Indexes FollowSymLinks
#   AllowOverride None
#   Require all granted
#</Directory>

# AccessFileName: The name of the file to look for in each directory
# for additional configuration directives.  See also the AllowOverride
# directive.
#
AccessFileName .htaccess

...以下是特定于相关网站的conf文件的内容:

<VirtualHost *:80>
   ServerName www.local_example.com
   ServerAlias local_example.com
   ServerAdmin serveradmin@gmail.com

   DocumentRoot /var/www/example.com
   <Directory /var/www/example.com/>
       Options Indexes FollowSymLinks MultiViews
       # pcw AllowOverride None
       AllowOverride All
       Order allow,deny
       allow from all
       # This directive allows us to have apache2's default start page
       # in /apache2-default/, but still have / go to the right place
       # Commented out for Ubuntu
       #RedirectMatch ^/$ /apache2-default/
   </Directory>

   ErrorLog /home/admin/Apache_Logs/local_example.com_error.log

   # Possible values include: debug, info, notice, warn, error, crit,
   # alert, emerg.
   LogLevel debug

   CustomLog /home/admin/Apache_Logs/local_example.com_access.log combined
   ServerSignature On

</VirtualHost>

1 个答案:

答案 0 :(得分:1)

如果/subdirectory是文件系统上的物理目录而/subdirectory/index.html是实际文件,则当前指令已包含必要的异常...如果请求的URL映射到,则不应重写URL物理目录或文件。

但是,要明确包含/subdirectory的例外,您可以执行以下操作:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !^subdirectory index.php

仅处理未启动/subdirectory的网址。 (并不是在将URL路径与RewriteRule模式匹配时删除了目录前缀,因此它应该是subdirectory,而不是/subdirectory。)

或者,您可以在.htaccess创建一个额外的/subdirectory/.htaccess,然后只需启用重写引擎:

# /subdirectory/.htaccess
RewriteEngine On

默认情况下不会继承mod_rewrite指令,因此这应该完全覆盖父.htaccess文件中的mod_rewrite指令。 (请注意,可能仍会处理来自不同模块的其他指令。)

更新:我在.htaccess文件中看不到任何会直接导致这些症状的内容,但是,以下内容确实需要修复/整理......

# Do not allow Perl script hackers, as they are probably just feeding useless Adsense "directory" sites
RewriteBase /
RewriteCond %{HTTP_USER_AGENT} libwww-perl.*
RewriteRule .* - [F,L]

# Filter for most common exploits
RewriteCond %{HTTP_USER_AGENT} libwww-perl [OR]
RewriteCond %{QUERY_STRING} tool25 [OR]
RewriteCond %{QUERY_STRING} cmd.txt [OR]
RewriteCond %{QUERY_STRING} cmd.gif [OR]
RewriteCond %{QUERY_STRING} r57shell [OR]
RewriteCond %{QUERY_STRING} c99 [OR]

上面的第二个代码块(&#34;过滤最常见的漏洞和#34;)不完整,不应该有一个尾随的OR标记(可能会阻止所有人! )。这两个代码块也重复相同的代码,应该组合在一起。 RewriteBase指令也是多余的,可以删除。以上内容应改写为:

# Do not allow Perl script hackers, as they are probably just feeding useless Adsense "directory" sites
# and Filter for most common exploits
RewriteCond %{HTTP_USER_AGENT} libwww-perl [OR]
RewriteCond %{QUERY_STRING} tool25 [OR]
RewriteCond %{QUERY_STRING} cmd.txt [OR]
RewriteCond %{QUERY_STRING} cmd.gif [OR]
RewriteCond %{QUERY_STRING} r57shell [OR]
RewriteCond %{QUERY_STRING} c99
RewriteRule .* - [F]

F标志隐含L,因此此处不需要L标记。

更新#2:再一次,我在VirtualHost容器中看不到会导致这些问题的任何内容(尽管如此,老实说,我很难想象甚至会想到什么可能会导致这种行为。)

但是,以下行是可疑的:

Options Indexes FollowSymLinks MultiViews

为什么需要MultiViews?另外,您需要Indexes吗?大多数站点将禁用这些选项,因为它们可能会暴露您的文件结构并导致意外行为(除非该行为是故意的)。但是,mod_rewrite需要FollowSymLinks

如果不需要这些选项,请尝试删除它们:

选项FollowSymLinks

顺便提一下,也可以使用以下指令在.htaccess中禁用这些选项(请注意,这里的选项前面带有-):

Options -Indexes -MultiViews