使用 Eventlet 从 WSGI 应用程序获取客户端 IP 地址

Posted

技术标签:

【中文标题】使用 Eventlet 从 WSGI 应用程序获取客户端 IP 地址【英文标题】:Obtaining Client IP address from a WSGI app using Eventlet 【发布时间】:2011-12-11 17:04:21 【问题描述】:

我目前正在编写一个基于 Python Eventlet 库 (http://eventlet.net/doc/) 的基本调度模型服务器。查看了 Eventlet 上的 WSGI 文档(http://eventlet.net/doc/modules/wsgi.html),我可以看到 eventlet.wsgi.server 函数除了客户端之外还记录了 x-forwarded-for 标头IP地址。

然而,获得它的方法是附加一个类似文件的对象(默认为 sys.stderr),然后让服务器通过管道将其连接到该对象。

我希望能够从应用程序本身(即具有 start_response 和 environ 作为参数的函数)中获取客户端 IP。事实上,环境键将是完美的。有没有办法简单地获取 IP 地址(即通过环境字典或类似的方法),而不必以某种方式重定向日志对象?

【问题讨论】:

【参考方案1】:

你想要的是 wsgi environ,特别是 environ['REMOTE_ADDR']

但是,如果涉及代理,则REMOTE_ADDR 将是代理的地址,并且客户端地址将(很可能)包含在HTTP_X_FORWARDED_FOR 中。

在大多数情况下,这里有一个功能可以满足您的需求(全部归功于Sævar):

def get_client_address(environ):
    try:
        return environ['HTTP_X_FORWARDED_FOR'].split(',')[-1].strip()
    except KeyError:
        return environ['REMOTE_ADDR']

您可以通过编写一个简单的 wsgi 应用程序并将浏览器指向它来轻松查看 wsgi 环境中包含的内容,例如:

from eventlet import wsgi
import eventlet

from pprint import pformat

def show_env(env, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    return ['%s\r\n' % pformat(env)]

wsgi.server(eventlet.listen(('', 8090)), show_env)

将两者结合起来......

from eventlet import wsgi
import eventlet

from pprint import pformat

def get_client_address(environ):
    try:
        return environ['HTTP_X_FORWARDED_FOR'].split(',')[-1].strip()
    except KeyError:
        return environ['REMOTE_ADDR']

def show_env(env, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    return ['%s\r\n\r\nClient Address: %s\r\n' % (pformat(env), get_client_address(env))]

wsgi.server(eventlet.listen(('', 8090)), show_env)

【讨论】:

谢谢Marty,事实上,我的下一步就是按照你在第二个sn-p 中的建议去做。也感谢指出代理信息,如果我在前面放了一个负载均衡器,这肯定会引起一些混乱。查看了 WSGI 规范 link,我发现 REMOTE_ADDR 不是必需变量,这可能是我困惑的根源! 我正在阅读有关此标头的一些文档,在我看来,客户端 IP 将是 X-Forwarded-For 中的第一个 ip。所以第一次返回的最后一点应该是.split(',')[0].strip()。参考:developer.mozilla.org/en-US/docs/Web/HTTP/Headers/…

以上是关于使用 Eventlet 从 WSGI 应用程序获取客户端 IP 地址的主要内容,如果未能解决你的问题,请参考以下文章

WSGI:使用 AJAX 从 python 脚本中获取字符串

如何在 Visual Studio 2017 中将包添加到 python

flask-socketio 在安装了 eventlet 的 aws 上不起作用

openstack中eventlet使用

Eventlet heroku flasksocketio 应用程序不工作

如何使用 mod_wsgi 从 django 访问 mod_ssl 环境变量?