gpt4 book ai didi

PHP Profiler - 使用 C++ 从 PHP 扩展获取客户端 IP 和 URL

转载 作者:行者123 更新时间:2023-11-28 04:33:16 26 4
gpt4 key购买 nike

我用 c++ 创建了一个 php 扩展,它跟踪每个请求的调用图。现在,我想获取每个请求的远程 ip 地址和 URL 详细信息。在 CentOS 7.5PHP 5.6.36 中尝试(禁用线程安全),当用户给出的每个请求(浏览器)到达时,apache 将控制权交给 PHP 模块,当它被处理进入响应阶段时。Zend 引擎的每个事务都会调用 PHP_RINIT_FUNCTION()。我试图在 PHP_RINIT_FUNCTION(apm) 函数中获取服务器名称和远程地址及其详细信息,如下所示,

zval *args;
char * name = "REMOTE_ADDR";
int len = sizeof("REMOTE_ADDR");
if ( (zend_hash_find(&EG(symbol_table), name,len, (void **) &args) != FAILURE) || PG(http_globals)[TRACK_VARS_SERVER] || zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, name,len, (void **) &args) != FAILURE)
{
// success
//converts args(zval*) to string
}
else
{
//failed
//can't get REMOTE address
}

上面的做法对吗??如果是这样,每个请求都会失败。我哪里错了?如果有的话,还有什么选择?

最佳答案

我过去成功的做法是从 $_SERVER 超全局数组变量中读取这些值。为了使用 $_SERVER(尤其是从 RINIT 上下文),您必须确保已调用其自动全局回调。 PHP 通常在第一次访问用户空间时调用它(换句话说,PHP 延迟加载超全局变量)。

为此,您从 auto_globals 哈希表中查找 zend_auto_global 值并调用自动全局回调。您应该始终检查以确保 $_SERVER 没有事先加载;尽管在您的情况下,您是从 RINIT 调用它,因此它始终不会被加载。

调用自动全局回调后,您现在可以像访问 symbol_table 哈希表中的任何其他全局变量一样访问 $_SERVER

这是我的一个名为 uniauth 的扩展的示例(有关 Github 上的完整上下文,请参阅 this link):

/* Make sure $_SERVER is auto loaded already. */
if (!zend_hash_exists(&EG(symbol_table),"_SERVER",8)) {
if (zend_hash_find(CG(auto_globals),"_SERVER",8,(void**)&auto_global) != FAILURE) {
auto_global->armed = auto_global->auto_global_callback(auto_global->name,
auto_global->name_len TSRMLS_CC);
}
else {
zend_throw_exception(NULL,"could not activate _SERVER",0 TSRMLS_CC);
return 0;
}
}

在代码库的这个特定部分,扩展使用 $_SERVER 中的信息生成重定向 URI。下面的代码显示了如何使用服务器变量来生成 URI(有关 Github 上的完整上下文,请参阅 this link):

/* Get information about the protocol, host and port number from the _SERVER
* superglobal. We use HTTPS, HTTP_HOST and SERVER_PORT keys to resolve the
* scheme, host and port. I know of no better way to do this unfortunately
* with the PHP/ZEND API. The sapi globals just don't have what I need.
*/
if (zend_hash_find(&EG(symbol_table),"_SERVER",8,(void**)&arr) == FAILURE) {
zend_throw_exception(NULL,"no _SERVER superglobal",0 TSRMLS_CC);
return 0;
}
server = Z_ARRVAL_PP(arr);
if (zend_hash_find(server,"HTTPS",6,(void**)&val) != FAILURE) {
if (Z_TYPE_PP(val) != IS_STRING || strcmp(Z_STRVAL_PP(val),"off") != 0) {
https = 1;
}
}
if (zend_hash_find(server,"HTTP_HOST",10,(void**)&val) != FAILURE
&& Z_TYPE_PP(val) == IS_STRING)
{
host = Z_STRVAL_PP(val);
}
else {
zend_throw_exception(NULL,"no HTTP_HOST within _SERVER found",0 TSRMLS_CC);
}

在评论中,我哀叹这样一个事实,即如果不模仿您在用户空间代码中所做的事情,就无法做到这一点。您可以在扩展中访问 SAPI 全局结构,但它没有我的项目(和您的)所需的所有信息。参见 the relevant structures在 PHP header 中了解更多信息。

关于PHP Profiler - 使用 C++ 从 PHP 扩展获取客户端 IP 和 URL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52288781/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com