PHP 扩展 - 获取当前请求 IP 地址

2016-07-05  本文已影响330人  Bun_Wong

在 PHP 中获取 IP 地址通常都是来自 $_SERVER 全局变量中,比如

$_SERVER['HTTP_CLIENT_IP'];
// OR
$_SERVER['HTTP_X_FORWARDED_FOR'];
// OR
$_SERVER['HTTP_X_REAL_IP'];  // 更多自定义的 key
// OR
$_SERVER['REMOTE_ADDR'];

也有可能在被前端 Web server 或 load balance 附加到请求头上,如 nginx 中可能设置了

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 

根据上面的逻辑,我简单实现了如下的一个方法

// azalea.h
PHP_FUNCTION(azalea_ip);
// azalea.c

/* {{{ azalea_getmodel
 */
PHP_FUNCTION(azalea_ip)
{
    zval *server, *field;
    zend_string *ip = NULL;

    server = zend_hash_str_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER") - 1);
    if (Z_TYPE_P(server) == IS_ARRAY) {
        if ((field= zend_hash_str_find(Z_ARRVAL_P(server), "HTTP_CLIENT_IP", sizeof("HTTP_CLIENT_IP") - 1)) &&
                Z_TYPE_P(field) == IS_STRING) {
            ip = Z_STR_P(field);
        } else if ((field = zend_hash_str_find(Z_ARRVAL_P(server), "HTTP_X_FORWARDED_FOR", sizeof("HTTP_X_FORWARDED_FOR") - 1)) &&
                Z_TYPE_P(field) == IS_STRING) {
            ip = Z_STR_P(field);
        } else if ((field = zend_hash_str_find(Z_ARRVAL_P(server), "REMOTE_ADDR", sizeof("REMOTE_ADDR") - 1)) &&
                Z_TYPE_P(field) == IS_STRING) {
            ip = Z_STR_P(field);
        }
    }
    if (ip) {
        zend_string_copy(ip);
    } else {
        ip = zend_string_init("0.0.0.0", sizeof("0.0.0.0") - 1, 0);  // 默认值
    }
    RETURN_STR(ip);
}
/* }}} */

当然了,PHP 通过 $_SERVER 甚至 request header 来获取 IP 都不是绝对靠谱的方法,还得看架构和运行环境。

上一篇下一篇

猜你喜欢

热点阅读