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'] 这个环境变量么?
这个坑谁来填?
这种错误会误导很多开发者!!!
简单来说: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'] 只能通过非命令行方式获取!
说明:以下是 代理转发场景下,需要获取客户端真实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";
}
$data['server']['HTTP_X_REAL_IP']
看到了“CNM”三个刺眼的字母,顿时觉得题主不仅能力“高”得出奇,素质更是令人震惊。结果最后证明文档并无错误,不知题主脸红不红,疼不疼,声音响不响。
教程哪里误导开发者了呢? 我认为是你理解的有问题,列几点自己的认识:
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进程转发来的】;
文档中这一章节并没有错误,不管是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,如果这里有问题几年前就被发现了,不会遗留到今天。
你本身就没分清楚 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,查找以下方法:
$_SERVER 就是在这里设置的。
手册并没有写错。