【问题标题】:Redirect subfolder to root and hide it in the url将子文件夹重定向到根目录并将其隐藏在 url
【发布时间】:2017-02-01 15:31:59
【问题描述】:

感谢this answerthis answer,我已经设法从目录中“重新设置”根目录,以便将公共文件与配置、帮助程序和控制器分开。

但是我意识到,如果用户输入 http://domain.com/public,它不会重定向到 http://domain.com,这对 SEO 是有害的,因为机器人会将它们视为两个 url,因此会重复。

我需要 301 重定向 /public 到 root 但只要我在尝试。它不起作用。

我的 htaccess 如下所示:

# Options
Options +FollowSymLinks +MultiViews -Indexes
DirectorySlash off

# Enable Rewrite Engine
RewriteEngine on
RewriteBase /

# Exceptions
RewriteCond %{REQUEST_URI} ^/(images|javascripts|stylesheets)/ [NC]
RewriteRule ^ - [L]

# www to non-www
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%2://%1%{REQUEST_URI} [L,R=301]

# Make /public like it was root
RewriteCond %{THE_REQUEST} /public/([^\s]+) [NC]
RewriteRule ^ /%1 [NC,L,R]
RewriteCond %{REQUEST_URI} !^/public
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /public/$1 [NC,L,QSA]

# Error pages
ErrorDocument 403 /errors/403.php
ErrorDocument 404 /errors/404.php
ErrorDocument 500 /errors/500.php

<files .htaccess="">
  order allow,deny
  deny from all
</files>

这样会重定向到http://domain.com//

我该如何解决这个问题?

编辑

我的网站目录结构是:

·
|__data
|__controllers
|__helpers
|__partials
|__layouts
|__images
|__javascripts
|__stylesheets
|__public
   |__index.php
   |__subfolder
      |__index.php

在根目录下不会有任何 index.php 页面。所以我需要创建/public 目录,因为它是我的根目录,以便将用户不必看到的配置和其他目录分开。

【问题讨论】:

  • public/ 中是否也有 .htaccess 文件?还有什么不适合你?
  • @anubhava 在/public 中只有像 url 一样工作的公共文件。 /public 的子目录也可用作链接。该文件夹内没有.htaccess。它不起作用的是,如果用户键入http://domain.comhttp://domain.com/public/,浏览器将显示相同的页面。错误是/public 以这种方式创建了两个链接,这将为 Google 生成重复项。我需要删除网址中的public,就像它是由斜杠和扩展名组成的一样

标签: apache .htaccess redirect mod-rewrite


【解决方案1】:

将您的 2 个public/ 相关规则替换为:

# add a trailing slash if public/$1 is a directory
RewriteCond %{DOCUMENT_ROOT}/public/$1 -d
RewriteRule ^(.*?[^/])$ %{REQUEST_URI}/ [L,R=301,NE]

# Make /public like it was root
RewriteCond %{THE_REQUEST} \s/+public/(\S*)\s [NC]
RewriteRule ^ /%1 [L,R=301,NE]

# internally add public/ to URIs
RewriteRule ^(?!public/).*$ public/$0 [L,NC]

如果您将 URL 用于子目录,则没有第一个尾部斜杠添加规则,例如http://domain.com/subfolder 然后在第三条规则之后在 URI 中添加 public/ 它在内部变为 http://domain.com/public/subfolder 这是一个有效的目录和 Apache 的 mod_dir 模块在最后添加一个斜杠,执行 301 重定向到 http://domain.com/public/subfolder/ 和这个将公开 public/ 部分给您的客户。

当第一个斜杠出现时,我们检查目标是否是目录,并在原始 non-/puclic/ URL 本身中添加一个斜杠。

【讨论】:

  • 这仅适用于第一级。当我输入 http://domain.com/public 时,它会重定向到 root,这没关系。但是如果我输入http://domain.com/subfolder,它将显示http://domain.com/public/subfolder/
  • 那是因为您在目录后缺少斜杠。当您在浏览器中输入:http://domain.com/subfolder/ 时会发生什么(不要忘记在每次测试之前清除浏览器缓存
  • 哦,好的,我明白了.. 但是如果用户不输入斜杠,实际上总是会发生这种情况怎么办?
  • 我认为问题在于您在 RewriteCond 中的意思是 (.*?) 而不是 (\s*)。或者可能是 ([^s]*)。
  • 使用 \s* 您只匹配(和捕获) /public/ 之后的空格这就是为什么它不适用于该公共目录的子目录 - 因为它们不匹配该正则表达式。
【解决方案2】:

这里有很多事情你需要解决,但它的核心似乎在这里:

# Make /public like it was root
RewriteCond %{THE_REQUEST} /public/([^\s]+) [NC]
RewriteRule ^ /%1 [NC,L,R]
RewriteCond %{REQUEST_URI} !^/public
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /public/$1 [NC,L,QSA]

该块将生成一个循环。它说“如果 URL 包含 public,则将其重定向到 root,但如果它不包含 public,则将其重定向到 public”。

我认为你想要做的只是:

RewriteRule ^public/(.*) /$1 [R=301,L]

还值得指出的是,底部的块不会做任何事情。我怀疑你的意思是:

<Files .htaccess>

不过,你可以试试

<FilesMatch ^\.>

对于所有“点文件”。

【讨论】:

  • 你的意思是我必须删除整个块并用那个字符串替换它?
  • 是的,没错。或者,或者,将整个内容替换为: Redirect 301 /public/ /
  • That block is going to generate a loop. 不,没有重定向循环,测试一下。
  • @dcdeiv 说您收到错误但没有提及错误日志所说的内容对尝试帮助您没有多大帮助。
  • 是的,@ezra-s 知道 403 是什么。他是 Freenode 上 #httpd 的常客之一。 (路过!我们很乐意得到您的帮助!)但是,403 可能有几个不同的原因(配置、权限、selinux 等),因此错误日志消息可以让您立即得到答案,而不是猜测和试验.
【解决方案3】:

好的,通过您的编辑,现在看来您所问的问题与我最初的解释相反。在我看来,您好像在引入一层额外的复杂性,以保护一开始就不应该在文档目录中的文件。

我建议更多的是从安全角度而不是 httpd 配置角度。如果文件不打算公开,请将它们移出文档目录。您最终会在文档目录中获得常规内容,以及图像、js 和 css,以及在它之外的其他内容。

如果您坚持使用 mod_rewrite 来完成此操作,我建议您使用以下方法:

RewriteCond %{DOCUMENT_ROOT}public%{REQUEST_FILENAME} -f
RewriteRule ^ /public%{REQUEST_URI} [PT]

但是,请注意,这实际上并不能解决问题,因为“私人”内容仍然存在,在文档目录中,等待有人弄清楚如何获取它。

我建议您退后一步,弄清楚您实际要解决的问题是什么。如果是文档根目录中存在私有文件的问题,正确的解决方案是将它们移出该文档根目录,而不是试图绕过它们。

【讨论】:

  • 我希望我可以将它们移出www 文档。但我没有 20 美元/月,也没有几乎 0.10 美元/小时来支付 VPS。我的提供商不允许这样做。
  • 好的,这很公平。那么我建议,而不是所有这些重新映射,是明确禁止访问敏感文件。如果文件名是可预测的,您可以使用 块执行此操作,或者在“私有”目录中的 .htaccess 文件中仅使用“要求全部拒绝”。这降低了复杂性,并提高了安全性。
  • 您的意思是按照上面的建议将它们添加到&lt;FilesMatch ^\.&gt;
  • 例如,如果“私有”文件被命名为 something.conf,您可以使用 块来保护它们。另一方面,如果 data/ 目录都是私有的,则在其中放置一个 .htaccess,其中包含“要求所有被拒绝”,仅此而已。通过这种方式,对这些文件的请求会导致禁止消息,而不是重写某些聪明或知识渊博的人可能会找到解决方法。 (我不熟悉你使用的框架,所以我无法推测具体情况。)
  • 好的!我懂了!我一定会做到的!我没有使用框架,因为在这里,在意大利,如果你想使用它们,你必须支付 VPS :(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-23
  • 2017-01-29
  • 2021-09-03
  • 2011-01-19
  • 2016-06-27
相关资源
最近更新 更多