django 取得发布信息用户的Ip 总是取得127.0.0.1这个, 并不是真实用户的ip?

class tkinfo(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name = _('author'), on_delete=models.CASCADE)
    title = models.CharField(max_length=255, verbose_name = u'信息标题')
    body = models.TextField()
    excerpt = models.CharField(_(u'话题简介'), default='', max_length=2000, blank=True, null = True)
    ip_user = models.GenericIPAddressField(unpack_ipv4=True, blank=True, null=True) 

ip_user = models.GenericIPAddressField(unpack_ipv4=True, blank=True, null=True)
用这个以前是可以取得用发布信息用户的真实ip地址的

最近换了服务器。centos 宝塔 搭建的环境django2.2 + python3.x + nginx +uwsgi

取得的ip地址都是127.0.0.1 了。
查了半天也没发现哪里有问题?
有知道或遇到过这问题的吗?
多谢

image.png

image.png

阅读 3.5k
3 个回答

你拿的是 Nginx 请求后端时的 IP,自然是 127.0.0.1。

存在转发时,需要取 XFF 头来获得 IP。

https://developer.mozilla.org...

Nginx 转发配置添加

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

你通过nginx http 反向代理请求过来的,在服务端看来它当然就是来自于127.0.0.1的请求啊(nginx和你的后端在一台服务器上,通过环回口访问的)。

解决这种问题你可以加一个自定义的header,在你的配置案例中就是多让nginx传递了一个X-Forwarded-For,这个非标准请求头通常也是各大CDN会带上的,你可以将用户ip从这个头拿出来。

看你用了uwsgi,还有一种解决方案是不走http反向代理,而是直接反向代理到uwsgi的unix domain socket上,这样你的程序直接就可以拿到客户端的访问ip了。nginx也是支持uwsgi反向代理的,详细内容可以参考nginx官访文档的uwsgi_pass指令: https://nginx.org/en/docs/htt...

一个使用sock文件的配置范例:

location / {
  uwsgi_pass unix:///tmp/myapp.sock;
  include uwsgi_params;
}

如果你的nginx是自己编译的,不存在uwsgi_params配置文件的话(这个文件一般你用各大Linux发行版官方仓库或者nginx官方仓库 https://nginx.org/en/linux_pa... 安装的软件包都会带有),那你把include uwsgi_params;这一行替换为下面内容:

uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;

然后修改你的uwsgi.ini配置,创建这个unix domain socket文件就行了:

[uwsgi]
socket = /tmp/myapp.sock
chmod-socket = 666
... 其他你的uwsgi配置 ...

重启uwsgi就会发现创建了一个socket文件/tmp/myapp.sock

这个过程本质上和apache通过proxy_ajp模块反向代理tomcat的过程是一样的,也就是不走http协议,就可以直接拿到真实的client ip了。

本机反向代理如果能用unix domain socket尽可能直接用unix domain socket,这个是安全性最高的,也是性能最好的,没有额外的性能开销,而TCP协议是有性能开销的。

要获取代理IP, 要设置一个可信代理的IP地址的, 否则不会取 x-forword-xxx 头的.

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题