Rails生产环境Devise记录127.0.0.1为用户IP,如何获取真实IP?
这个问题我之前帮不少开发者处理过,核心原因是你的Passenger作为应用服务器,是跑在Web代理服务器(比如Nginx或Apache)后面的——主机提供商通常会这么配置。当用户请求过来时,先经过Web服务器再转发给Passenger,Rails默认会把转发请求的Web服务器IP(也就是127.0.0.1)当成客户端IP,导致Devise记录错误。咱们一步步来修复:
1. 确保Web服务器传递真实IP请求头
首先得确认你的Web服务器(Nginx/Apache)在转发请求给Passenger时,已经把用户的真实IP通过请求头传递过去了:
如果你用的是Nginx
在对应站点的配置文件里,添加或确认以下配置:
proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme;
这两行会把用户的真实IP放到X-Forwarded-For头里,同时传递请求的协议(HTTP/HTTPS)。修改完后记得重启Nginx:sudo service nginx restart。
如果你用的是Apache
在站点配置里添加或确认:
RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s" RequestHeader set X-Forwarded-Proto "https" env=HTTPS
同样是把真实IP注入到请求头中,修改后重启Apache:sudo service apache2 restart。
2. 让Rails信任代理服务器
Rails默认不会随意信任代理发来的请求头,得明确告诉它哪些代理是可信的。打开config/environments/production.rb,添加以下配置:
# 因为Web服务器和Passenger在同一台机器,所以信任本地IP config.action_dispatch.trusted_proxies = ['127.0.0.1', '::1'] # 若需要信任整个本地IP段,也可以用IPAddr范围 # config.action_dispatch.trusted_proxies = [IPAddr.new('127.0.0.0/8'), IPAddr.new('::1/128')]
添加后重启你的Rails应用(Passenger会自动检测配置变化,或手动执行:passenger-config restart-app /path/to/your/app)。
3. 验证配置是否生效
为了确认真实IP能被正确获取,可以在某个控制器里临时加个测试动作:
# 比如在application_controller.rb里 def test_ip render plain: "Remote IP: #{request.remote_ip}\nX-Forwarded-For: #{request.headers['X-Forwarded-For']}" end
然后在config/routes.rb里添加对应路由:
get 'test_ip', to: 'application#test_ip'
部署后访问https://your-domain.com/test_ip,如果返回的Remote IP是你的真实公网IP,就说明配置成功了,Devise的trackable模块也会自动记录这个真实IP。
4. 检查Devise的Trackable配置(可选)
如果上面的步骤都做完还是有问题,确认一下你的用户模型里的trackable是否正常启用,并且没有自定义覆盖IP获取逻辑。Devise的trackable默认是用request.remote_ip来记录IP的,如果你自己写了自定义的update_tracked_fields方法,要确保里面用的是正确的IP来源。
内容的提问来源于stack exchange,提问作者Ivan Baksheev

