我在运行 Ubuntu 的 AWS EC2 实例上托管 Ruby on Rails 应用程序,并利用 Let's Encrypt for SSL。在我的 Nginx 配置 (
/etc/nginx/sites-available/example
) 中,当 config.force_ssl = true
中的 config/environments/production.rb
行被注释掉时,从 HTTP 到 HTTPS 的重定向可以正常工作。
下面是 Nginx 配置的片段:
server {
listen 80;
server_name example.com www.example.com;
# Redirect HTTP to HTTPS
# return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
但是,当我取消注释此行时,网站无法加载,导致浏览器中出现“ERR_TOO_MANY_REDIRECTS”错误。但是,如果我注释掉
config.force_ssl = true
行,应用程序将无法正确重定向到 HTTPS 站点,从而导致 Rails 日志中出现以下错误:
HTTP Origin header (https://example.com) didn't match request.base_url (http://example.com)
在尝试解决重定向问题,同时在 Ruby on Rails 应用程序中维护 SSL 强制执行时,我最初注释掉了
config.force_ssl = true
文件中的 config/environments/production.rb
行。这成功地阻止了“ERR_TOO_MANY_REDIRECTS”错误,但导致不正确地重定向到 HTTPS 站点,Rails 日志显示 HTTP Origin header
不匹配错误就证明了这一点。
为了进一步排除故障并解决问题,我检查了 Nginx 配置 (
/etc/nginx/sites-available/example
)。最初,从 HTTP 到 HTTPS 的重定向是通过取消监听端口 80 的服务器块中的 return 301 https://$host$request_uri;
行注释来实现的。但是,当取消注释 config.force_ssl = true
行时,它导致了上述重定向循环。
总而言之,我尝试调整 Nginx 配置并切换
config.force_ssl
设置。我的期望是成功实施 SSL,同时确保正确重定向,而不会遇到“ERR_TOO_MANY_REDIRECTS”错误或 CSRF 令牌不匹配问题。但是,这些尝试导致了重定向循环或不正确的 HTTPS 重定向。我寻求有关如何纠正此问题并实现预期结果的指导。
在多次尝试调整 nginx 配置以解决“ERR_TOO_MANY_REDIRECTS”错误并在 Ruby on Rails 应用程序中强制执行 SSL 时实现正确的 HTTPS 重定向后,我终于发现了问题的根本原因。默认情况下,在 Rails 7.2 中,
config.force_ssl = true
中的config/environments/production.rb
行设置为 true,这有助于在 Rails 应用程序中强制执行 SSL。因此,这导致了重定向循环,表明我的 Nginx 设置和 Rails 在处理 SSL 重定向方面存在冲突。
但是,经过进一步的调查和实验,我发现取消注释
config.assume_ssl = true
中的config/environments/production.rb
行可以有效解决该问题。此配置设置指示 Rails 假设所有传入请求都是安全的,这与我的应用程序访问已通过 SSL 终止反向代理 (Nginx) 处理的事实相一致。