使用 Nginx 位置配置重定向到 HTTPS 和 Apex 域

Ray*_*Air 4 nginx heroku

我想通过使用位置块的 nginx 配置在我的应用程序中强制使用 HTTPS 和顶点域(例如https://example.com)。我目前有以下 nginx_app.conf 文件(适用于顶点和 www 子域,以及 http 和 https):

location / {
    try_files $uri @rewriteapp;
}

location @rewriteapp {
    rewrite ^(.*)$ /app.php/$1 last;
}

location ~ ^/(app|config)\.php(/|$) {
    # fastcgi_pass directives go here...
}
Run Code Online (Sandbox Code Playgroud)

为了强制使用顶点域和 https,我尝试使用 if 语句如下,检查 $scheme 和 $host 变量,但我收到一个错误,表明页面没有正确重定向。我还添加了一个 HSTS 指令

location / {
    if ($scheme = http) {
        rewrite ^/(.*) https://$host/$1 permanent;
    }
    if ($host = www.example.com) {
        rewrite ^/(.*) https://example.com/$1 permanent;
    }
    try_files $uri @rewriteapp;
}

location @rewriteapp {
    rewrite ^(.*)$ /app.php/$1 last;
}

location ~ ^/(app|config)\.php(/|$) {
    # fastcgi_pass directives go here...
    add_header Strict-Transport-Security "max-age=86400";
}
Run Code Online (Sandbox Code Playgroud)

使用 nginx 配置强制 http 和顶点域的正确方法是什么?顺便说一句,我正在使用 heroku(带有 DNSimple)来部署我的应用程序,因此我希望以下两个域都能工作:https://example.herokuapp.comhttps://example.com

更新:我尝试将位置块外的 if 语句移动到默认服务器块中(单击此处),并按如下方式更改返回的重写,但它仍然不起作用。我在请求 http 时仍然收到“页面没有正确重定向”,在请求 www 子域时出现“无法连接错误”。

if ($scheme = http) {
    return 301 https://$host$request_uri;
}
if ($host = www.example.com) {
    return 301 https://example.com$request_uri;
}

location / {
    try_files $uri @rewriteapp;
}

location @rewriteapp {
    rewrite ^(.*)$ /app.php/$1 last;
}

location ~ ^/(app|config)\.php(/|$) {
    # fastcgi_pass directives go here...
    add_header Strict-Transport-Security "max-age=86400";
}
Run Code Online (Sandbox Code Playgroud)

adr*_*aan 8

1)这里的问题可能是 Heroku 负载均衡器。当访问请求进入您的应用程序时,请求又是 HTTP。这只是内部路由。你不能针对$scheme. 但是 Heroku 为$http_x_forwarded_proto这些请求设置了一个标头。

if ($http_x_forwarded_proto != "https") {
  return 301 https://$host$request_uri;
}
Run Code Online (Sandbox Code Playgroud)

来源:https : //discussion.heroku.com/t/force-ssl-and-no-www-with-nginx-configuration/856


2a)要指向 no-www,您可以使用以下命令:

server {
  listen <%= ENV["PORT"] %>;
  server_name "~^www\.(.*)$";
  return 301 https://$1$request_uri;
}
Run Code Online (Sandbox Code Playgroud)

对于测试,您应该使用 302 而不是 301,因为浏览器会缓存 301 重定向。

这也会将您重定向到 https。但只能来自 www 子域,因此您必须保留上述$http_x_forwarded_proto重定向。

2b)另一种选择是使用带有 www 子域的服务器块并将其重定向到非 www 域,如下所示:

server {
  listen <%= ENV["PORT"] %>;
  server_name www.example.com;

  location / {
    return 301 https://example.com$request_uri;
  }
}

server {
  listen <%= ENV["PORT"] %>;
  server_name example.com;

  location / {
    try_files $uri $uri/ /index.html =404;
  }
}
Run Code Online (Sandbox Code Playgroud)

<%= ENV["PORT"] %>代码来自一个buildpack。在 Heroku 上,您无法侦听端口 80。