【问题标题】:Unexpected behavior with custom .htaccess rewrite rules自定义 .htaccess 重写规则的意外行为
【发布时间】:2016-01-18 02:48:21
【问题描述】:

所以我一直在研究一些无法按预期工作的重写规则。这些是我尝试重写的一些示例请求:

/             -> /index.php?page=Home
/Home         -> /index.php?page=Home
/Teaching/Foo -> /index.php?page=Teaching&id=Foo
/Teaching/Bar -> /index.php?page=Teaching&id=Bar
/Download/ue8 -> /index.php?action=Download&id=ue8
/Download/24a -> /index.php?action=Download&id=24a
(default)     -> /index.php?page=Home
** OR ALTERNATIVELY **
(default)     -> /index.php?page=FileNotFound
(and maybe rewrite the visible URL to /FileNotFound)

我主要想隐藏尽可能多的 url,并防止目录列表和直接访问我位于特定文件夹中的文件,并且只允许通过 /Download/FileId 访问可下载的文件,同时可以访问我用于不同讲座的常用页面通过/Teaching/SomeLecture

到目前为止,我一直将这个 sn-p 用于 /Home/Teaching 的东西:

RewriteEngine On
RewriteBase /

# Redirect Trailing Slashes
RewriteRule ^(.*)/$ /$1 [L,R=301]

# Handle Front Controller
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^Teaching/([A-Za-z0-9]*)$ index.php?page=Teaching&id=$1 [L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^Home$ index.php?page=Home [L]

RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s(.*)/index\.php [NC]
RewriteRule ^ %1 [R=301,L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [L,R=301]

我并不完全确定所有这些指令,我注意到它目前存在一些缺陷。

  1. 试图访问不存在的文件,例如/Files/Bad/Path.pdf,将用户转发到/?page=Home,这应该重定向到//Home或显示/index.php?page=FileNotFound的内容,而不改变URL或重定向到/FileNotFound,这取决于@的规则987654333@。我不确定哪种解决方案可能最适合这种情况。
  2. 尝试访问某些确实存在的文件夹会导致无限重定向循环,而不存在的文件夹显然会重定向到/。在这两种情况下,我想重定向到/FileNotFound 感觉不错?

您能否制定一套在这种情况下可能适合我需要的规则?

【问题讨论】:

    标签: regex apache .htaccess mod-rewrite redirect


    【解决方案1】:

    您的 .htaccess 中有许多多余的指令。将所有 .htaccess 替换为:

    # Turn off mod_spelling
    <IfModule mod_speling.c>
       CheckSpelling off
       CheckCaseOnly off
    </IfModule>
    
    Options -MultiViews
    RewriteEngine On
    RewriteBase /
    
    # block direct access to file and directories in these directories
    RewriteCond %{REQUEST_URI} !\.(?:jpe?g|gif|bmp|png|tiff|css|js)$ [NC]
    RewriteCond %{REQUEST_FILENAME} -d [OR]
    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule ^(Templates|Files) - [NC,F]
    
    # remove index.php
    RewriteCond %{THE_REQUEST} /index\.php [NC]
    RewriteRule ^(.*?)index\.php$ /$1 [L,R=301,NC,NE]
    
    # Redirect Trailing Slashes
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)/$ /$1 [L,R=301]
    
    # Handle Front Controller
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(Download|Teaching)/([\w-]+)/?$ index.php?page=$1&id=$2 [L,QSA,NC]
    
    RewriteRule ^(Home)?/?$ index.php?page=Home [L,NC,QSA]
    

    确保在测试之前清除浏览器缓存。

    【讨论】:

    • 倒数第二行有一个小错误,您使用的是QSA.NC 而不是QSA,NC。此外,我遇到了服务器的一些有趣行为。如果我尝试访问一个文件,它会尝试更正输入错误的 url,在某些情况下它无法决定并显示this。除了我迄今为止的规则之外,您是否碰巧知道如何完全拒绝对index.php 以外的文件的直接访问?除了这个小问题之外,这似乎是我一直在寻找的东西。
    • 详细说明我的评论:当我尝试直接访问/Files/Ana14/ 时,它会转发到/Files/Ana15/,因为它是唯一具有类似模式的现有文件夹,然后它会显示 403 错误消息。在我的第二种情况下,在 300 状态代码中有多种可能性,但我不想展示这一点。在这两种情况下,我都想显示适当的错误页面。
    • 禁用mod_spelling 确实修复了多项选择!我想我应该使用Deny from all 在其他目录中创建新的.htaccess 文件以禁用对这些文件的直接访问?
    • 我的index.php 包括特定的图像文件和一些幕后的 php 文件和一些 pdf 文件(如果用户请求下载)。我想阻止访问文件夹/Files/Templates 等以及它们的子文件夹和实际文件,如 pdf。这就是为什么我认为专门针对每个目录的.htaccessDeny from all 会更好。
    • 这个版本似乎满足了我的所有需求——非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-24
    • 1970-01-01
    • 2013-05-22
    相关资源
    最近更新 更多