Rails应用程序在代理后面使用https重定向?

21

我的nginx.conf文件中的服务器声明:

    listen       1.2.3.4:443 ssl;
    root /var/www/myapp/current/public;
    ssl on;
    ssl_certificate /etc/nginx-cert/server.crt;
    ssl_certificate_key /etc/nginx-cert/server.key;
    location / {
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header Host $http_host;
          proxy_redirect off;

          if (!-f $request_filename) {
            proxy_pass http://upstreamy;
            break;
          }
     }

nginx.conf中的upstream声明:

upstream upstreamy {
    server unix:/var/www//myapp/shared/sockets/unicorn.sock fail_timeout=0;
}

这很好,我的应用可以通过https://somehost访问。

但是应用程序生成的重定向 URL 是 http 类型,因此当使用 Devise 进行身份验证时,/ 会被重定向到http://somehost/user/sign_in而不是 https(从 Rails 应用程序的视角来看,它仍然是 http)。

我尝试过

proxy_pass https://upstreamy;

但这只是尝试加密 nginx 和运行 Rails 应用程序的 unicorn 之间的流量。

我还尝试在 application_helper.rb 中:

# https://dev59.com/8nI-5IYBdhLWcg3w0L_x
def url_options
  super
  @_url_options.dup.tap do |options|
  options[:protocol] = Rails.env.production? ? "https://" : "http://"
  options.freeze
end

但是似乎它不起作用。

该怎么解决?

编辑:因此,目标不是使rails应用程序需要ssl,也不强制使用ssl;目标是在重定向时使rails应用程序生成https:// url…(我认为所有其他url都是相对的)。

2个回答

51

你需要添加以下行:

proxy_set_header X-Forwarded-Proto https;

例如:

location / {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-Forwarded-Proto https;
      proxy_redirect off;

      if (!-f $request_filename) {
        proxy_pass http://upstreamy;
        break;
      }
 }

3
太棒了!设置nginx可能会非常麻烦。非常麻烦... :) - Yosep Kim
我无法使用proxy_set_header,但我将所有内容转发到我的代理服务器上进行“post”方法,并为get重写了url。目前工作得非常好。 - nembleton
11
在许多情况下(但也许不是你的情况),最好使用“proxy_set_header X-Forwarded-Proto $scheme;”来正确传递X-Forwarded-Proto到上游应用程序,无论是在http还是https上。当负载均衡器处理https时,这尤其有用。 - jmervine
1
如果负载均衡器终止SSL,通过HTTP与nginx通信,后者再通过HTTP与Rails通信,那么$scheme不就是(错误的)HTTP了吗?在这种情况下,您仍希望Rails生成HTTPS URL。@jmervine - Patrick
把这段代码放在哪里?在监听80还是443下面?你能分享你的完整配置吗? - buncis

-2
你可以通过传递 :protocol => "https" 来使用 redirect_to 重定向功能。
你可以将以下内容添加到 application.rb 文件中,以将其设置为默认值。
Rails.application.routes.default_url_options[:protocol]= 'https'

参考资料: https://dev59.com/NW025IYBdhLWcg3wST6Q#6101147


1
这不是透明的,并且将应用程序代码绑定到特定的部署配置。 - eprothro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接