program tip

Rails 앱에서 force_ssl로 무한 리디렉션 루프가 발생하는 이유는 무엇입니까?

radiobox 2020. 11. 20. 08:49
반응형

Rails 앱에서 force_ssl로 무한 리디렉션 루프가 발생하는 이유는 무엇입니까?


API 컨트롤러가 SSL을 사용하도록하고 싶으므로 nginx.conf에 다른 수신 지시문을 추가했습니다.

upstream unicorn {
  server unix:/tmp/unicorn.foo.sock fail_timeout=0;
}

server {
  listen 80 default deferred;
  listen 443 ssl default;
  ssl_certificate /etc/ssl/certs/foo.crt;
  ssl_certificate_key /etc/ssl/private/foo.key;

  server_name foo;
  root /var/apps/foo/current/public;

  try_files $uri/system/maintenance.html $uri/index.html $uri @unicorn;

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://unicorn;
  }

  error_page 502 503 /maintenance.html;
  error_page 500 504 /500.html;
  keepalive_timeout 5;
}

문제없이 nginx conftest를 통과합니다. 또한 force_sslApiController에 지시문을 추가했습니다.

class ApiController < ApplicationController
  force_ssl if Rails.env.production?

  def auth
    user = User.authenticate(params[:username], params[:password])
    respond_to do |format|
      format.json do
        if user
          user.generate_api_key! unless user.api_key.present?
          render json: { key: user.api_key }
        else
          render json: { error: 401 }, status: 401
        end
      end
    end
  end

  def check
    user = User.find_by_api_key(params[:api_key])
    respond_to do |format|
      format.json do
        if user
          render json: { status: 'ok' }
        else
          render json: { status: 'failure' }, status: 401
        end
      end
    end
  end
end

SSL을 사용하지 않을 때 잘 작동했지만 이제를 시도 curl --LI http://foo/api/auth.json하면 제대로 리디렉션 https되지만 http://foo/api/auth무한 리디렉션 루프 끝나 도록 계속 리디렉션됩니다 .

내 경로는 단순히

get "api/auth"
get "api/check"

nginx 0.7.65와 함께 Ruby 1.9.2에서 Rails 3.2.1을 사용하고 있습니다.


이 요청이 HTTPS 종료 요청인지 여부에 대한 정보를 전달하지 않습니다. 일반적으로 서버에서 "ssl on;" 지시문은 이러한 헤더를 설정하지만 결합 된 블록을 사용하고 있습니다.

랙 (및 force_ssl)은 다음을 통해 SSL을 결정합니다.

  • If the request came in on port 443 (this is likely not being passed back to Unicorn from nginx)
  • If ENV['HTTPS'] == "on"
  • If the X-Forwarded-Proto header == "HTTPS"

See the force_ssl source for the full story.

Since you're using a combined block, you want to use the third form. Try:

proxy_set_header X-Forwarded-Proto $scheme;

in your server or location block per the nginx documentation.

This will set the header to "http" when you come in on a port 80 request, and set it to "https" when you come in on a 443 request.


Try setting this directive in your nginx location @unicorn block:

proxy_set_header X-Forwarded-Proto https;

I had this same issue and investigating the Rack middleware handler (not force_ssl but similar) I could see that it was expecting that header to be set to determine if the request was already processed as being SSL by nginx.

참고URL : https://stackoverflow.com/questions/9448168/why-am-i-getting-infinite-redirect-loop-with-force-ssl-in-my-rails-app

반응형