问题描述
我有一个使用 Laravel 5 作为 API 构建的应用程序.我的 .htaccess 文件中有以下内容将所有路由重定向到 https:
I have an application built with Laravel 5 acting as an API. I have the following in my .htaccess file to redirect all routes to https:
RewriteEngine On
# Force SSL
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
这适用于以下情况:
https://example.com/route
但是如果我尝试使用 http 访问它,则会抛出 MethodNotAllowedHttpException.它正确重定向到 https,但似乎没有正确跟随 POST 请求,因为我所有的路由都只允许 POST.
but throws a MethodNotAllowedHttpException if i try to access it with http. It correctly redirects to https, but seems to be not correctly following with the POST request, since all my routes only allow POST.
有没有什么办法可以在不改变我的路由以允许 GET 的情况下解决这个问题?
Is there any way to fix this without changing my routes to allow GET as well?
推荐答案
为了强制使用 https,您的 RewriteRule 需要强制外部重定向.就您的规则而言,您正在强制进行 301 重定向 (R=301
).大多数浏览器和客户端都设计为自动跟踪重定向,但它们(错误地)通过 GET 请求这样做.
In order to force https, your RewriteRule is required to force an external redirect. In the case of your rule, you're forcing a 301 redirect (R=301
). Most browsers and clients are designed to automatically follow redirects, but they (incorrectly) do so with a GET request.
因此,当客户端向 http://example.com/route
发送带有数据的 POST 请求时,您的服务器会响应 301 重定向到 https://example.com/route
,然后客户端向新 URL 发出不带数据的 GET 请求.如您所见,您不能仅仅更改路由以接受 GET 请求,因为原始 POST 请求中发送的数据将被丢弃.
So, when a client sends a POST request with data to http://example.com/route
, your server responds with a 301 redirect to https://example.com/route
, and then the client makes a GET request without the data to the new URL. As you can see, you can't just change your routes to accept GET requests as well, because the data sent in the original POST request will be dropped.
一种选择是添加重写条件以不重定向 POST 请求:
One option would be to add a rewrite condition to not redirect POST requests:
# Force SSL
RewriteCond %{HTTPS} !=on
RewriteCond %{REQUEST_METHOD} !=POST
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
然而,这几乎违背了您尝试完成的目的.整个概念是在任何地方强制使用 https.除了向您的应用程序 POST 数据时,在任何地方强制执行它都是愚蠢的.
However, this pretty much defeats the purpose of what you're attempting to accomplish. This whole concept is to force https everywhere. It would be silly to enforce it everywhere except when POSTing data to your application.
另一种可能的选择是将您的 301 重定向更改为 307 重定向.尽管客户端不应该更改 301/302 重定向的请求方法,但由于规范和现有功能的含糊不清,大多数客户端都会这样做.因此,添加了 307 的具体想法是,如果使用此状态代码,则不得更改请求方法.但是,307 被归类为临时重定向",因此它不会被缓存并且可能会影响您的 SEO.此外,此状态已添加到 HTTP/1.1 规范中,因此您可能会遇到一些不知道如何处理 307 的客户端.
Another possible option would be to change your 301 redirect to a 307 redirect. Even though clients aren't supposed to change the request method for 301/302 redirects, most clients do due to ambiguity in the specs and existing functionality. Because of this, 307 was added with the specific idea that if this status code is used, the request method MUST NOT be changed. However, 307 is classified as a "temporary redirect", so it won't be cached and may affect your SEO. Additionally, this status was added in the HTTP/1.1 spec, so you may run into some clients that don't know how to process a 307.
您最好的选择可能只是拒绝不安全的 POST 请求.或者,将它们重定向到一个错误页面,说明您不接受非安全的 POST 请求.
Your best option is probably just to reject non-secure POST requests. Or, redirect them to an error page explaining you don't accept non-secure POST requests.
RewriteEngine On
# Forbid non-secure POSTs
RewriteCond %{HTTPS} !=on
RewriteCond %{REQUEST_METHOD} =POST
RewriteRule ^ / [F,L]
# Force SSL
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
这篇关于Laravel 5 - 后路由上的 htaccess HTTPS 重定向不起作用.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!