workerman PHP CLI模式 获得客户端IP问题

-3

官方文档里【透过nginx/apache代理如何获取客户端真实ip】这一章




我们先看文档


1、先在nginx里配置


  location /wss
{
proxy_pass http://127.0.0.1:8282;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
#这部分是利用http头透传真实客户端ip
proxy_set_header X-Real-IP $remote_addr;
}

2、workerman从nginx设置的header里读取客户端ip


   $connection->onWebSocketConnect = function($connection){
/**
* connection对象本没有realIP属性,这里给connection对象动态添加个realIP属性
* 记住php对象是可以动态添加属性的,你也可以用自己喜欢的属性名
*/
$connection->realIP = $_SERVER['HTTP_X_REAL_IP'];
};

好的,坑来了?





PHP在CLI模式下能有 $_SERVER['HTTP_X_REAL_IP'] 这个环境变量么?



这个坑谁来填?

已邀请:

walkor

赞同来自: TimeUser zhouaini528 hongs

文档中这一章节并没有错误,不管是workerman的onWebSocketConnect 还是gatewayWorker中start_gateway.php里的onWebSocketConnect 都可以使用 $_SERVER['HTTP_X_REAL_IP ']来获得nginx转发来的ip。因为workerman包括gatewayWorker在websocket握手的时候会给$_SERVER['HTTP_X_REAL_IP ']赋值,所以可以拿到这个值。


workerman文档已经写了很多年了,N多开发者使用这个方法获得nginx代理后的客户端真实IP,如果这里有问题几年前就被发现了,不会遗留到今天。

blogdaren - 专注C编程、PHP内核、LINUX、VIM【http://www.phpcreeper.com】

赞同来自: q13113671764

教程哪里误导开发者了呢? 我认为是你理解的有问题,列几点自己的认识:
1、既然你提到了CLI模式和非CLI模式,这个本身就是错误的认识,workerman只能工作在CLI模式,什么时候有了非CLI模式一说呢?
2、workerman和gatewayworker本身就不是一个东西:
workerman一个是底层的socket框架,gatewayworker则是基于workerman针对特定长连接应用场景开发出来的应用框架;
3、对于websocket协议,其握手阶段是基于http协议实现的,所以在onWebSocketConnect($connection, $http_header)回调中我们可以直接或间接的解析到$_SERVER变量,上面说了:workerman和gatewayworker本身就不是一个东西,workerman对于$_SERVER变量可以直接拿到;但是gatewayworker的Gateway::onWebSocketConnect() Events::onWebSocketConnect() 回调是有些许差别的,前者也可以直接拿到$_SERVER变量【手册里写的很清楚在start_gateway.php里的这个回调中来获取nginx设置的http头,所以哪里误导开发者了呢?】,而后者虽然直接拿不到该变量里的某些字段,但是我们可以从$http_header这个变量里头随时拿到你想要的东西【因为它是Gateway进程转发来的】;

qplchen

赞同来自:

这种错误会误导很多开发者!!!


简单来说:Workerman目前在下面情况下,是不能获取到真实客户端IP的


1、先以PHP CLI模式启动【websocket】服务端协议 websocket://127.0.0.1:8443
2、nginx添加http代理【https://wss.xxx.com】,转到【http://127.0.0.1:8443
3、websocket服务端通过 $_SERVER['HTTP_X_REAL_IP'] 系统变量,是不能获取到任何IP信息的
4、通过实践会直接报错,找不到 HTTP_X_REAL_IP


因为 $_SERVER['HTTP_X_REAL_IP'] 只能通过非命令行方式获取!

qplchen

赞同来自:

说明:以下是 代理转发场景下,需要获取客户端真实IP的解决方案


1、项目转用 GatewayWorker 框架


2、在 onWebSocketConnect 事件中,重要的事情说3遍
2、在 onWebSocketConnect 事件中,重要的事情说3遍
2、在 onWebSocketConnect 事件中,重要的事情说3遍


3、因为onConnect 事件属于TCP握手完成事件,只能通过$_SERVER['REMOTE_ADDR'] 获取IP,不能获取到代理场景下客户真实IP


4、```php
public static function onWebSocketConnect($client_id, $data)
{
var_export($data);
echo $data['HTTP_X_REAL_IP']."\n";
}




## 千万别相信教程里使用 $_SERVER['HTTP_X_REAL_IP'],CNM

WilliamA

赞同来自:

你本身就没分清楚 workerman 和 gatewayworker 吧?一会 workerman,一会又 gatewayworker,将 workerman 的手册当成 gatewayworker 的手册了。


另外,workerman 本身就以 cli 模式运行,cli 是 sapi 的一种,sapi 还包括 fastcgi、cgi 等。不知道你指的非命令行又是什么?


$_SERVER 是 PHP 根据 nginx 的请求报文设置的。如果你用的是 gatewayworker,你可以简单地将 gatewayworker 理解成另一个 nginx,它将 php 接收到的请求报文再转发给其它 php 进程(也就是 businessworker),在这个过程中,businessworker 并没有将将请求内容设置到 $_SERVER 中,当然如果你自己有能力可以修改 gatewayworker 源码的 BusinessWorker.php,查找以下方法:


public function onGatewayMessage($connection, $data)

$_SERVER 就是在这里设置的。


手册并没有写错。

要回复问题请先登录注册