rewrite和if应该避免使用Nginx。有一句名言是“Nginx不是Apache”:换句话说,Nginx有比重写更好的方法来处理URL。从技术上讲,return仍然是重写模块的一部分,但它不携带rewrite的开销,也不像if那样充满警告。 Nginx在why if is "evil"上有一个完整的页面。它还提供了一个建设性的页面,解释why rewrite and if are bad,以及如何解决它。以下是页面关于rewrite和if的说明: 这是一种错误的、繁琐的、无效的方式。 你可以使用return来解决这个问题:
server {
listen 443 ssl;
# You will need a wildcard certificate if you want to specify multiple
# hostnames here.
server_name domain.example www.domain.example;
# If you have a certificate that is shared among several servers, you
# can move these outside the `server` block.
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/cert.key;
# 301 indicates a permanent redirect. If your redirect is
# temporary, you can change it to 302 or omit the number
# altogether.
# $http_host is the hostname and, if applicable, port--unlike $host,
# which will break on non-standard ports
# $request_uri is the raw URI requested by the client, including any
# querystring
return 301 http://$http_host$request_uri;
}
server {
# If you're using https between servers, you'll need to modify the listen
# block and ensure that proper ssl_* statements are either present or
# inherited.
listen 80;
server_name domain.example;
if ($http_x_forwarded_proto = https) {
rewrite ^(?!/secure)/ http://$http_host$request_uri? permanent;
}
if ($http_x_forwarded_proto != https) {
rewrite ^/secure(?:/|$) https://$http_host$request_uri? permanent;
}
}
9条答案
按热度按时间c6ubokkw1#
为什么这样的东西有用?起初,我不确定这是否可以做到。但它提出了一个有趣的问题。
您可以尝试在配置文件中放置重定向语句,然后重新启动服务器。可能会发生两种情况:
1.服务器将发出重定向-你似乎想要什么。
1.服务器将首先进行https交换,然后发出重定向,在这种情况下,有什么意义?
如果我能想出更具体的东西,会增加更多。
更新:(几个小时后) 你可以试试这个。你需要把它放在你的nginx.conf**文件中-
向客户端发送永久重定向。我假设你正在使用端口443(默认)的https。
添加此内容,以便端口80上的正常http请求不受干扰。
*更新: 2016年12月18日 * -
server_name _
应该在nginx版本> 0.6.25中使用,而不是server_name _ *
(感谢@Luca Steeb)fcipmucu2#
rewrite
和if
应该避免使用Nginx。有一句名言是“Nginx不是Apache”:换句话说,Nginx有比重写更好的方法来处理URL。从技术上讲,return
仍然是重写模块的一部分,但它不携带rewrite
的开销,也不像if
那样充满警告。Nginx在why
if
is "evil"上有一个完整的页面。它还提供了一个建设性的页面,解释whyrewrite
andif
are bad,以及如何解决它。以下是页面关于rewrite
和if
的说明:这是一种错误的、繁琐的、无效的方式。
你可以使用
return
来解决这个问题:如果你预计会有很多机器人不发送
Host
报头,你可以使用$host
而不是$http_host
,只要你坚持使用端口80和443。否则,您需要动态填充$http_host
替代。这段代码只要出现在server
的根目录中(而不是location
块中),即使使用了if
,也是高效和安全的。但是,您需要使用默认服务器才能使其适用,这应该避免使用https。如果您想对特定路径强制SSL/TLS,但在其他情况下禁止它:
如果您的服务器没有与客户端直接通信-例如,如果您使用CloudFlare-事情会变得有点复杂。您需要确保与客户端直接通信的任何服务器都将适当的
X-Forwarded-Proto
头添加到请求中。使用这个是一个混乱的命题;有关完整的解释,请参见IfIsEvil。为了使其有用,
if
块不能在location
块内,原因很复杂。这迫使使用rewrite
进行URI测试。如果您需要在生产服务器上使用此功能,则...别这样。你这样想:如果您已经超越了Apache,那么您已经超越了这个解决方案。/secure、/secure/和/secure/中的任何内容都将强制使用https,而所有其他URI都将强制使用http。
(?! )
PCRE结构是negative lookahead assertion。(?: )
是non-capturing group。xmq68pz93#
ztyzrc3y4#
这个问题更适合于serverfault.com网站。
一个更好的重定向到http的方法:
这避免了重写中的“if”子句和正则表达式,这是迄今为止其他解决方案的特征。两者都有性能方面的影响,尽管在实践中,您必须有相当多的流量才能发挥作用。
根据您的设置,您可能还希望在listen子句中指定ip,或者在上面的servername子句中指定。它将适用于所有域名的所有端口443请求。您通常希望每个域的IP与https,所以大多数情况下,将上述内容绑定到IP比将其绑定到域名更重要,但也有一些变化,例如,所有域都是一个域的子域。
编辑:TLS现在已经接近通用了,它的服务器名称标识(SNI)允许多个域上的HTTPS站点共享一个IP。写得很好here
bwntbbo35#
这帮助了我:
ktca8awb6#
打开您的域的Nginx配置文件。此文件通常位于Linux系统上的/etc/nginx/sites-available/目录中。比在HTTPS(SSL)配置的服务器块中,添加以下行来执行重定向:
保存并退出文本编辑器,然后测试你的nginx配置:
sudo nginx -t
如果temrinal显示“ok”和“valid”,那么你可以使用以下命令重新加载nginx配置:
sudo systemctl reload nginx
此配置将使用301(永久)重定向将所有HTTPS请求重定向到HTTP
9o685dep7#
不是一个合适的解决方案,但我能够通过使用Cloudflare解决我的用例,它为我透明地处理SSL。
2ic8powd8#
唯一简单的规则已经在我上面的帖子中解释过了:
sd2nnvve9#
插入此代码后,HTTP默认服务器的所有流量都会重定向到HTTPS。