https://signup.example.com
它只能通过HTTPS访问,但我担心人们可能会通过HTTP偶然发现它并得到404。
我在nginx中的html / server块如下所示:
html {
server {
listen 443;
server_name signup.example.com;
ssl on;
ssl_certificate /path/to/my/cert;
ssl_certificate_key /path/to/my/key;
ssl_session_timeout 30m;
location / {
root /path/to/my/rails/app/public;
index index.html;
passenger_enabled on;
}
}
}
我可以添加些什么,以便那些去
http://signup.example.com
的人被重定向到https://signup.example.com
? (仅供参考,我知道有些Rails插件可以强制使用SSL
,但希望避免这种情况)#1 楼
根据nginx陷阱,最好使用$request_uri
省略不必要的捕获。在这种情况下,请添加问号以防止Nginx将任何查询参数加倍。server {
listen 80;
server_name signup.mysite.com;
rewrite ^ https://$server_name$request_uri? permanent;
}
评论
或者,根据您链接的网站,“更好”:返回301 http://domain.com$request_uri;
– nh2
2012年8月14日下午4:56
一则评论。 $ server_name $获取第一个server_name变量。因此,如果您的配置中没有非FQN名称,请注意这一点
–engineerDave
2012年8月15日在15:48
@ nh2这是文档错误的另一种情况,因为使用return 301 ...会在重写方法实际起作用时导致“重定向过多”错误。
–迈克·伯大尼(Mike Bethany)
15年7月2日在12:06
现在已记录为“也很糟糕”。 @MikeBethany return 301确实可以正常工作,除非(我想)您正在通过同时侦听两个端口来触发它以获取正确的URL(配置示例触发问题:以serverfault.com/a/474345/29689的第一个答案为准,然后忽略如果)。
–布莱布莱德
15年8月3日在8:57
我想知道这些年来发生了什么变化以及其他答案是否更好:serverfault.com/a/337893/119666
–瑞安
18年7月14日在0:59
#2 楼
官方方法中描述的最佳方法是使用return
指令:server {
listen 80;
server_name signup.mysite.com;
return 301 https://$server_name$request_uri;
}
评论
最短的答案,在我的情况下效果很好
–mateusz.fiolka
2012年9月8日在22:37
通常建议这样做,因为它会返回301永久移动(您的链接已永久移动)以及重写
– sgb
2014-12-17 17:17
即使您设置了proxy_set_header X-Forwarded-Proto https,它也不会导致“重定向过多”错误;
–迈克·伯大尼(Mike Bethany)
15年7月2日在12:03
@MikeBethany您是在定义监听443吗?在同一街区?
– Joe B
15年8月12日在18:06
这应该是公认的答案。
– sjas
16-09-13在10:08
#3 楼
如果要将它们全部保留在一个服务器块中,这是正确且最有效的方法:这里是相同的,但是效率更高,通过仅在http协议上运行重写,它避免了必须在每个请求中检查$ scheme变量。但认真的说,这是一件很小的事情,您无需将它们分开。
server {
listen 80;
listen [::]:80;
listen 443 default_server ssl;
server_name www.example.com;
ssl_certificate /path/to/my/cert;
ssl_certificate_key /path/to/my/key;
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
}
评论
太好了,即使这个答案是正确的,一些胆小鬼还是拒绝了这个答案,却没有说出原因。也许那些“如果是邪恶的”信徒中的另一个。如果您不愿阅读有关If的Nginx文档,您会知道IfIsNOTEvil,只是CERTAIN在location {}上下文中使用了它,我们在这里都不会做。我的回答绝对是正确的做事方式!
–DELETEDACC
13年2月26日在21:50
我没有对此表示拒绝,但我想指出的是,在最新版本中,默认值已更改为“ default_server”。
– spudder
13-10-22在3:32
如果第二种解决方案效率更高,则第一种解决方案可能不是最有效的。您甚至描述了为什么不应该在其中使用if:“它避免了每次请求都必须检查$ scheme变量”。不使用ifs的意义不仅在于性能,还在于声明性而非强制性。
– pepkin88
16-10-24在11:12
+1代表if($ scheme = http)
–费尔南多·科什(Fernando Kosh)
16-11-27在21:34
如其他答案中所述,应在此处使用$ host。
– Artem Russakovskii
17年1月7日,9:25
#4 楼
如果您正在使用新的双重HTTP和HTTPS服务器定义,则可以使用以下命令:server {
listen 80;
listen [::]:80;
listen 443 default ssl;
server_name www.example.com;
ssl_certificate /path/to/my/cert;
ssl_certificate_key /path/to/my/key;
if ($ssl_protocol = "") {
rewrite ^ https://$server_name$request_uri? permanent;
}
}
这似乎对我有用,并且不会导致重定向循环。
编辑:
已替换:
rewrite ^/(.*) https://$server_name/ permanent;
使用Pratik的重写行。
评论
@DavidPashley,您的解决方案对我来说就像一个魅力。谢谢
–贾伊什·戈帕兰(Jayesh Gopalan)
2012年5月17日12:23
如果您正在使用新的双重HTTP和HTTPS服务器定义,则应将其分开。
–VBart
13年2月23日在14:42
优雅而完美的作品!
– jacktrade
2014年9月17日于17:01
这是适用于我的Laravel / Homestead Nginx配置的唯一解决方案。
–贾里德·艾特尼尔(Jared Eitnier)
2015年1月5日于17:04
重写行也应该返回301 https:// $ server_name $ request_uri;因为这是首选方法。
–贾里德·艾特尼尔(Jared Eitnier)
2015年4月20日15:17
#5 楼
还有一个变体,保留了Host:请求标头,并在nginx陷阱上遵循了“ GOOD”示例:server {
listen 10.0.0.134:80 default_server;
server_name site1;
server_name site2;
server_name 10.0.0.134;
return 301 https://$host$request_uri;
}
这里是结果。请注意,使用
$server_name
而不是$host
将始终重定向到https://site1
。# curl -Is http://site1/ | grep Location
Location: https://site1/
# curl -Is http://site2/ | grep Location
Location: https://site2/
# curl -Is http://site1/foo/bar | grep Location
Location: https://site1/foo/bar
# curl -Is http://site1/foo/bar?baz=qux | grep Location
Location: https://site1/foo/bar?baz=qux
评论
请注意,使用$ server_name代替$ host总是会重定向到https:// site1,这不是$ request_uri的目的吗?
–于尔根·保罗(JürgenPaul)
2014-4-27 9:49
$ request_uri不包含主机名或域名。换句话说,它始终以“ /”字符开头。
–彼得
2014年4月27日在11:17
迄今为止最好的答案。
–嘘
15年7月3日在14:42
我不确定为什么这个答案投票率太低。这是唯一值得使用的工具。
– zopieux
2015年12月8日在18:02
不能相信这么多人使用$ server_name这是正确的方法
–格雷格·恩尼斯(Greg Ennis)
16-6-29在2:14
#6 楼
server {
listen x.x.x.x:80;
server_name domain.tld;
server_name www.domian.tld;
server_name ipv4.domain.tld;
rewrite ^ https://$server_name$request_uri? permanent;
}
我认为这种方法效果更好。 x.x.x.x是您服务器的IP。如果您使用的是Plesk 12,则可以通过更改所需域的目录“ /var/www/vhosts/system/domain.tld/conf”中的“ nginx.conf”文件来实现。保存配置后,别忘了重启nginx服务。
评论
重写^ https:// $ host $ request_uri?常驻;会是一个更好的解决方案,因为您可能在虚拟主机上有多个服务器名称
–user333008
16 Jan 20 '15:39
#7 楼
我认为这是最简单的解决方案。仅将非HTTPS和非WWW流量都强制为HTTPS和www。server {
listen 80;
listen 443 ssl;
server_name domain.tld www.domain.tld;
# global HTTP handler
if ($scheme = http) {
return 301 https://www.domain.tld$request_uri;
}
# global non-WWW HTTPS handler
if ($http_host = domain.tld) {
return 303 https://www.domain.tld$request_uri;
}
}
编辑-2018年4月:没有IF的解决方案可以在我的文章中找到:https://stackoverflow.com/a/36777526/6076984
评论
在Nginx世界中,IF条件是否被认为是邪恶的和低效的?
–PKHunter
17年2月14日在20:09
是的,一般而言。但是对于这种简单的检查,我猜不会。我确实有一个适当的配置文件,尽管其中包含更多的代码编写,但完全避免了IF。
– stamster
17-2-22在19:29
Google建议使用301,而不是303。来源:support.google.com/webmasters/answer/6073543?hl = zh-CN
– dylanh724
18年4月17日在6:49
@DylanHunt-我只剩下303进行测试,请注意第一个处理程序设置为301,只有第二个我忘了更改:)另外,没有IF的解决方案:stackoverflow.com/a/36777526/6076984
– stamster
18年4月20日在18:27
评论
在Nginx中可能重复,如何在维护子域的同时将所有http请求重写为https?