出于安全原因,get_host()与META ['REMOTE_ADDR']

dir*_*ell 4 django django-forms django-views

我正在一个Django项目中,在该项目中,用户将根据位置获得自定义信息。为此,我使用他们的IP地址来标识他们的国家。为了使数据库中的数据保持一致,我需要确保我具有正确的IP。

我知道使用META通常会使用客户端浏览器发送的标头,但我不知道这是否适用于该REMOTE_ADDR属性。

TLDR:HttpRequest.get_host()和之间有什么区别HttpRequest.META['REMOTE_ADDR']

Ben*_*ueg 6

HttpRequest.get_host()和之间的区别HttpRequest.META['REMOTE_ADDR']是,第一个按优先级递减的顺序检查以下标头中的IP:

  1. HTTP_X_FORWARDED_HOST
  2. HTTP_HOST
  3. SERVER_NAME combined with SERVER_PORT

而第二个检查标头中的IP REMOTE_ADDR

返回的信息类型有很大的不同:get_host()将为您提供托管应用程序的服务器的名称,而不是客户端的IP。

更详细地,这里是实现get_host()

def get_host(self):
    """Returns the HTTP host using the environment or request headers."""
    # We try three options, in order of decreasing preference.
    if settings.USE_X_FORWARDED_HOST and (
        'HTTP_X_FORWARDED_HOST' in self.META):
        host = self.META['HTTP_X_FORWARDED_HOST']
    elif 'HTTP_HOST' in self.META:
        host = self.META['HTTP_HOST']
    else:
        # Reconstruct the host using the algorithm from PEP 333.
        host = self.META['SERVER_NAME']
        server_port = str(self.META['SERVER_PORT'])
        if server_port != ('443' if self.is_secure() else '80'):
            host = '%s:%s' % (host, server_port)

    allowed_hosts = ['*'] if settings.DEBUG else settings.ALLOWED_HOSTS
    domain, port = split_domain_port(host)
    if domain and validate_host(domain, allowed_hosts):
        return host
    else:
        msg = "Invalid HTTP_HOST header: %r." % host
        if domain:
            msg += "You may need to add %r to ALLOWED_HOSTS." % domain
        raise DisallowedHost(msg)
Run Code Online (Sandbox Code Playgroud)

如果要检查客户端IP地址,则可以使用以下标头(请参阅获取客户端IP地址:REMOTE_ADDR,HTTP_X_FORWARDED_FOR,还有什么有用吗?):

  • REMOTE_ADDR
  • HTTP_X_FORWARDED_FOR
  • HTTP_CLIENT_IP
  • HTTP_X_FORWARDED_FOR 可以是逗号分隔的IP列表
  • HTTP_X_FORWARDED
  • HTTP_X_CLUSTER_CLIENT_IP
  • HTTP_FORWARDED_FOR
  • HTTP_FORWARDED

如果您不知道选择哪一个(如果不是全部),则可以记录这些标头并随着时间的推移实用地添加新的检查。