.htaccess 重写 URL 并强制使用 https

.htaccess 重写 URL 并强制使用 https

网站:example.com

Joomla 子目录:example.com/joomla

我希望安装在 example.com/joomla 上的 Joomla 成为(或看起来像)网站的根目录即访问 example.com 的人会被重定向到 example.com/joompla/index.php,但仍会在 URL 栏中看到 example.com。我还想利用这个机会强制所有传入连接使用 HTTPS。我可以使用在线找到的脚本完成其中一个操作,但无法同时完成两个操作。

以下是我目前对 .htaccess 所掌握的内容:

RewriteEngine on
RewriteBase /

# Rewrites all URLS without joomla in them
RewriteCond %{REQUEST_URI} !^/joomla/

# Rewrites all URLS with example in them
RewriteCond %{HTTP_HOST} ^(www\.)?example\.

# Rewrite all those to insert /joomla
RewriteRule ^(.*)$ /joomla/$1 [L]

# This works SOME of the time to redirect to https
Header always set Content-Security-Policy "upgrade-insecure-requests;"

# If a request tries to access /joomla directly, redirect it to its secured canonical version
RewriteCond %{THE_REQUEST} joomla/
RewriteRule ^joomla/(.*) http://example.com/$1 [R=301,L]

在 Chrome 中,这种方法有时似乎有效,重定向到 Joomla 安装并切换到 https,但有时我需要反复强制重新加载才能到达那里。在 Firefox 中,这种方法从来都行不通,在极少数情况下,它完全加载了网站,但始终停留在 http 上。

我对 .htaccess 还很陌生,我不确定我是否已经开发出针对上述问题的最优雅或最全面的解决方案。我在网上看到过其他使用RewriteCond %{HTTPS} !=onRewriteCond %{SERVER_PORT} 80结合各种RewriteRule命令的示例,但我不确定如何将这些命令与现有的 URL 重写条件结合起来,因此我肯定我错过了一些边缘场景。

有经验的人能指导我吗?我将不胜感激。几天来我一直在尝试在线找到的脚本变体,但还没有找到咒语。

答案1

关于您现有指令的一些注意事项:

重写库 /

虽然您已定义RewriteBase,但它并未在任何指令中使用。RewriteBase仅适用于相对路径替代(您已在相关指令中明确使用了根相对 URL 路径)。

# Rewrites all URLS with example in them
RewriteCond %{HTTP_HOST} ^(www\.)?example\.

需要检查请求的主机名?除非您托管多个域(或子域),并且您不想应用此规则,否则状况是多余的。

# This works SOME of the time to redirect to https
Header always set Content-Security-Policy "upgrade-insecure-requests;"

绝不触发“重定向”,所以我不确定您在网络流量中看到了什么?

(事实上​​,您发布的代码中没有任何内容可以触发从 HTTP 到 HTTPS 的“重定向”。)

此 HTTP 响应标头会导致浏览器自动“升级”任何请求链接资源(CSS、JS、图像、外部资源等)从原本通过 HTTP 传输的初始 HTML(页面)响应(例如,因为实际 URL 包含http://...)转换为通过 HTTPS 传输。没有发生实际的“重定向”。并且,对于可能通过纯 HTTP 传输的初始 HTML 响应,什么也不会发生。

如果您已实施站点范围的 HTTP 到 HTTPS 重定向,并且所有链接资源都已是 HTTPS 或使用根相对(或协议相对)URL,则此标头并非绝对必要。但它确实提供了良好的安全网。但请注意,任何不支持 HTTPS 的链接资源都会中断 - 不会向用户发出浏览器警告。如果没有此标头,则用户可能会收到浏览器“混合内容”警告(并且链接的资源会失败)。

# If a request tries to access /joomla directly, redirect it to its secured canonical version
RewriteCond %{THE_REQUEST} joomla/
RewriteRule ^joomla/(.*) http://example.com/$1 [R=301,L]

RewriteCond指令(用于在“正常情况下”防止重定向循环)与joomla/请求的 URL 中的任何位置匹配,甚至在查询字符串中也是如此 - 这是不正确的,并且如果出现在 URL 路径或查询字符串的其他地方,可能会导致错误的重定向。例如,如果我简单地将其附加到任何 URL 的末尾,joomla/这将导致重定向循环。?joomla/

此“重定向”应内部重写。一般来说,“重定向”应该位于“重写”之前,以避免重定向重写的 URL 并将重写的 URL 暴露给您的用户。

正如评论中所述,此重定向是到 HTTP - 与您尝试执行的操作相反(并且在实现 HTTP 到 HTTPS 重定向时会导致一个小的重定向链)。

一些假设:

  • SSL 证书直接安装在应用程序服务器上,即没有 Cloudflare(Flexible-SSL)或其他管理 SSL 的前端代理。
  • 您没有使用任何其他子域名。只是www
  • 规范的主机名是非 www 的,即example.com(来自您问题中的重定向)。
  • 您此时尚未实施 HSTS,因此您可以example.com在单个重定向中重定向到 HTTPS 和规范主机名(即)。
  • Joomla 本身已配置为/joomla从 URL 中省略子目录。/joomla不存在于任何内部链接中,包括指向静态资源(CSS、JS、图像等)的链接。
  • 您没有从文档根目录提供任何文件。一切是进入/joomla子目录。

.htaccess场景#1-文档根目录中的单个文件。

(如评论中所述。)

.htaccess在这种情况下,安装子目录 ( ) 中没有“Joomla”文件/joomla,无法将您的 URL 路由到 Joomla 前端控制器(即index.php)。在这种情况下,index.php必须存在于 URL 中,并且您不能使用 Joomla 的“SEF”URL。

/.htaccess文件看起来就像这样:

RewriteEngine on

RewriteBase /joomla

# If a request tries to access /joomla directly, redirect it to its secured canonical 
RewriteCond %{THE_REQUEST} ^[A-Z]{3,7}\s/joomla
RewriteRule ^joomla(?:$|/(.*)) https://example.com/$1 [R=302,L]

# Canonicalise the hostname - ie. www to non-www and HTTPS
RewriteCond %{HTTP_HOST} ^www\.(.+?)\.?$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=302,L]

# Redirect remaining requests from HTTP to HTTPS
# The hostname must already be canonical at this point
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L]

# Rewrite everything to the /joomla subdirectory
# Uses the value defined in the RewriteBase directive above
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.*) $1 [L]

# Ensure that any linked resources are requested over HTTPS
Header always set Content-Security-Policy "upgrade-insecure-requests;"

请注意,我在这里使用了 302(临时)重定向来进行测试。始终先使用 302 重定向进行测试,只有在确认可以正常工作后才更改为 301(永久)。301 会被浏览器永久缓存,因此可能会使测试出现问题。

环境REDIRECT_STATUS变量用于确保我们只重写直接请求而不重写请求,其THE_REQUEST使用方式与第一条规则中的 大致相同。REDIRECT_STATUS在初始请求中为空,在第一次成功重写后设置为“200”(如 200 OK HTTP 响应状态)。该指令RewriteRule (.*) $1 [L]乍一看可能有点奇怪(它看起来像是重写为自身),但是,RewriteBase是结果替换的前缀,因此它实际上重写为/joomla/<url>

场景 #2 - 两个.htaccess文件:文档根目录和子目录

.htaccess子目录中的文件将/joomla.htaccessJoomla 附带的合理标准文件。这会将所有请求路由到 Joomla 前端控制器(即index.php),并允许使用 Joomla 的“SEF”URL(即您无需index.php在 URL 中明确包含)。

/.htaccess文件看起来就像这样:

RewriteEngine on

RewriteBase /joomla

# Canonicalise the hostname - ie. www to non-www and HTTPS
RewriteCond %{HTTP_HOST} ^www\.(.+?)\.?$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=302,L]

# Redirect remaining requests from HTTP to HTTPS
# The hostname must already be canonical at this point
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L]

# Rewrite everything to the /joomla subdirectory
# Uses the value defined in the RewriteBase directive above
RewriteRule (.*) $1 [L]

# Ensure that any linked resources are requested over HTTPS
Header always set Content-Security-Policy "upgrade-insecure-requests;"

/joomla请注意,从 URL 中删除子目录的重定向已被删除,需要放入/joomla/.htaccess文件中。(如果留在这里,那就完全是多余的。)

REDIRECT_STATUS这次你不需要检查环境变量/joomla/.htaccess,因为抓住重写请求后。(假设未启用 mod_rewrite 继承。)

如果您愿意,可以将指令移动到 - 这是可选的,因为无论如何它都会被“继承” Header/joomla/.htaccess

然后,该/joomla/.htaccess文件将包含如下内容:

# JOOMLA: Set Options here

RewriteEngine on

# If a request tries to access here directly then redirect back to root
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.*) https://example.com/$1 [R=302,L]

# JOOMLA: Rewrite rules to block out some common exploits.
# :

# Leave the RewriteBase directive commented out - it's not required
#RewriteBase /joomla

## Begin - Joomla! core SEF Section.
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

RewriteRule ^index\.php$ - [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
## End - Joomla! core SEF Section.

/joomla/.htaccess文件大致基于Joomla 网站上的代码但是,我省略了常用元素/注释,并将“SEF 部分”更改为与子目录相关。(Joomla 还使用效率较低的正则表达式,.*而不是简单的^。)

相关内容