我刚刚在 Webfaction 上部署了一个 Flask 应用程序,我注意到它request.remote_addr
总是127.0.0.1
. 这当然没有多大用处。
如何在 Flask on Webfaction 中获取用户的真实 IP 地址?
谢谢!
我刚刚在 Webfaction 上部署了一个 Flask 应用程序,我注意到它request.remote_addr
总是127.0.0.1
. 这当然没有多大用处。
如何在 Flask on Webfaction 中获取用户的真实 IP 地址?
谢谢!
如果 Flask 前面有代理,那么这样的事情会得到 Flask 中的真实 IP:
if request.headers.getlist("X-Forwarded-For"):
ip = request.headers.getlist("X-Forwarded-For")[0]
else:
ip = request.remote_addr
更新: Eli 在他的评论中提到了非常好的观点。如果您只是简单地使用它,可能会出现一些安全问题。阅读Eli 的帖子以获取更多详细信息。
Flask 的文档非常具体地介绍了推荐的反向代理服务器设置:
如果您使用 HTTP [反向] 代理后面的这些 [WSGI] 服务器之一部署应用程序,则需要重写一些标头才能使应用程序 [正确] 工作。WSGI 环境中的两个有问题的值通常是
REMOTE_ADDR
和HTTP_HOST
... Werkzeug 提供了一个修复程序,可以解决一些常见的设置,但您可能希望为特定设置编写自己的 WSGI 中间件。
还有关于安全考虑:
请记住,在非代理设置中使用此类中间件是一个安全问题,因为它会盲目信任可能由恶意客户端伪造的传入标头。
将request.remote_addr
返回客户端 IP 地址的建议代码(安装中间件)是:
from werkzeug.contrib.fixers import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app, num_proxies=1)
请注意默认num_proxies
情况1
下。它是应用程序前面的代理服务器数量。
实际代码如下(werkzeug==0.14.1
撰写本文时最新):
def get_remote_addr(self, forwarded_for):
if len(forwarded_for) >= self.num_proxies:
return forwarded_for[-self.num_proxies]
Webfaction 关于访问REMOTE_ADDR
的文档说:
... IP 地址可用作
HTTP_X_FORWARDED_FOR
标头中逗号分隔列表中的第一个 IP 地址。
他们没有说当客户端请求已经包含X-Forwarded-For
标头时他们会做什么,但按照常识,我会假设他们会替换它。因此对于 Webfactionnum_proxies
应该设置为0
.
Nginx 更明确的是$proxy_add_x_forwarded_for
:
“X-Forwarded-For”客户端请求标头字段,
$remote_addr
附加变量,用逗号分隔。如果客户端请求标头中不存在“X-Forwarded-For”字段,则该$proxy_add_x_forwarded_for
变量等于该$remote_addr
变量。
对于应用程序前面的 Nginxnum_proxies
应该保留默认值1
。
重写伊格纳斯的答案:
headers_list = request.headers.getlist("X-Forwarded-For")
user_ip = headers_list[0] if headers_list else request.remote_addr
记得阅读Eli关于欺骗注意事项的帖子。
您可以使用request.access_route
访问 ip 列表:
if len(request.access_route) > 1:
return request.access_route[-1]
else:
return request.access_route[0]
更新:
你可以这样写:
return request.access_route[-1]
问题是 Flask 前面可能有某种代理。在这种情况下,“真实”IP 地址通常可以在request.headers['X-Forwarded-For']
.