32

我刚刚在 Webfaction 上部署了一个 Flask 应用程序,我注意到它request.remote_addr总是127.0.0.1. 这当然没有多大用处。

如何在 Flask on Webfaction 中获取用户的真实 IP 地址?

谢谢!

4

5 回答 5

53

如果 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 的帖子以获取更多详细信息。

于 2012-10-07T18:12:32.757 回答
8

Werkzeug 中间件

Flask 的文档非常具体地介绍了推荐的反向代理服务器设置

如果您使用 HTTP [反向] 代理后面的这些 [WSGI] 服务器之一部署应用程序,则需要重写一些标头才能使应用程序 [正确] 工作。WSGI 环境中的两个有问题的值通常是REMOTE_ADDRHTTP_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

Nginx 更明确的是$proxy_add_x_forwarded_for

“X-Forwarded-For”客户端请求标头字段,$remote_addr附加变量,用逗号分隔。如果客户端请求标头中不存在“X-Forwarded-For”字段,则该$proxy_add_x_forwarded_for变量等于该$remote_addr变量。

对于应用程序前面的 Nginxnum_proxies应该保留默认值1

于 2018-06-28T17:11:59.813 回答
7

重写伊格纳斯的答案:

headers_list = request.headers.getlist("X-Forwarded-For")
user_ip = headers_list[0] if headers_list else request.remote_addr

记得阅读Eli关于欺骗注意事项的帖子。

于 2013-09-03T17:38:51.310 回答
5

您可以使用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]
于 2014-04-24T23:14:15.070 回答
3

问题是 Flask 前面可能有某种代理。在这种情况下,“真实”IP 地址通常可以在request.headers['X-Forwarded-For'].

于 2012-10-07T17:12:48.550 回答