php中getenv()和$_SERVER的用法区别

getenv 取得系统的环境变量,环境变量的格式为:key=value

语法: string getenv(string varname);

返回值: 字符串 函数种类: PHP 系统功能

内容说明
若正确取得环境变量 var_name,则返回变量值,失败则返回 false

下例可以取得用户浏览器所在机器的IP地址
<?php
      $ip = getenv(“REMOTE_ADDR”);
?>

$_SERVER是服务器超级全局变量数组

用$_SERVER['REMOTE_ADDR']同样可以获取到客户端的IP地址.

二者的区别在于:

getenv不支持IIS的isapi方式运行的php

 

$_SERVER 详细参数

PHP编程中经常需要用到一些服务器的资料,下面特把$_SERVER的详细参数整理,方便以后使用

$_SERVER['PHP_SELF']           # 当前正在执行脚本的文件名,与 document root相关

$_SERVER['argv']                       # 传递给该脚本的参数

$_SERVER['argc']                       # 包含传递给程序的命令行参数的个数(如果运行在命令行模式)

$_SERVER['GATEWAY_INTERFACE']       # 服务器使用的 CGI 规范的版本,例如,“CGI/1.1”

$_SERVER['SERVER_NAME']                      # 当前运行脚本所在服务器主机的名称

$_SERVER['SERVER_SOFTWARE']            # 服务器标识的字串,在响应请求时的头部中给出

$_SERVER['SERVER_PROTOCOL']            # 请求页面时通信协议的名称和版本。例如,“HTTP/1.0”

$_SERVER['REQUEST_METHOD']             # 访问页面时的请求方法,例如:“GET”、“HEAD”,“POST”,“PUT”

$_SERVER['QUERY_STRING']                    # 查询(query)的字符串

$_SERVER['DOCUMENT_ROOT']               # 当前运行脚本所在的文档根目录。在服务器配置文件中定义

$_SERVER['HTTP_ACCEPT']                        # 当前请求的 Accept: 头部的内容。

$_SERVER['HTTP_ACCEPT_CHARSET']    # 当前请求的 Accept-Charset: 头部的内容。例如:“iso-8859-1,*,utf-8”

$_SERVER['HTTP_ACCEPT_ENCODING']  # 当前请求的 DontTrackMeHere: 头部的内容,例如:“gzip”

$_SERVER['HTTP_ACCEPT_LANGUAGE']  # 当前请求的 Accept-Language: 头部的内容,例如:“en”

$_SERVER['HTTP_CONNECTION']               # 当前请求的 Connection: 头部的内容,例如:“Keep-Alive”

$_SERVER['HTTP_HOST']                              # 当前请求的 Host: 头部的内容

$_SERVER['HTTP_REFERER']                       # 链接到当前页面的前一页面的 URL 地址

$_SERVER['HTTP_USER_AGENT']               # 当前请求的 User-Agent: 头部的内容

$_SERVER['HTTPS']                                        # 如果通过https访问,则被设为一个非空的值(on),否则返回off

$_SERVER['REMOTE_ADDR']                      # 正在浏览当前页面用户的 IP 地址

$_SERVER['REMOTE_HOST']                       # 正在浏览当前页面用户的主机名

$_SERVER['REMOTE_PORT']                       # 用户连接到服务器时所使用的端口

$_SERVER['SCRIPT_FILENAME']                # 当前执行脚本的绝对路径名

$_SERVER['SERVER_ADMIN']                     # 管理员信息

$_SERVER['SERVER_PORT']                        # 服务器所使用的端口

$_SERVER['SERVER_SIGNATURE']            # 包含服务器版本和虚拟主机名的字符串

$_SERVER['PATH_TRANSLATED']             # 当前脚本所在文件系统(不是文档根目录)的基本路径

$_SERVER['SCRIPT_NAME']                        # 包含当前脚本的路径。这在页面需要指向自己时非常有用

$_SERVER['REQUEST_URI']                        # 访问此页面所需的 URI,例如,“/index.html”

 

打印 $_SERVER 结果

print_r($_SERVER);

打印结果如下:

Array ( 
[HTTP_HOST] => localhost 
[HTTP_CONNECTION] => keep-alive 
[HTTP_CACHE_CONTROL] => max-age=0 
[HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 
[HTTP_USER_AGENT] => Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 
[HTTP_DNT] => 1 
[HTTP_REFERER] => http://localhost/
[HTTP_ACCEPT_ENCODING] => gzip, deflate, sdch 
[HTTP_ACCEPT_LANGUAGE] => en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4 
[PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 
[SystemRoot] => /
[SERVER_SIGNATURE] => Apache/2.4.7 (Ubuntu) Server at localhost Port 80
[SERVER_SOFTWARE] => Apache/2.4.7 (Ubuntu) 
[SERVER_NAME] => localhost 
[SERVER_ADDR] => 127.0.0.1 
[SERVER_PORT] => 80 
[REMOTE_ADDR] => 127.0.0.1 
[DOCUMENT_ROOT] => /home/homer/workspace/ 
[REQUEST_SCHEME] => http 
[CONTEXT_PREFIX] => 
[CONTEXT_DOCUMENT_ROOT] => /home/homer/workspace/ 
[SERVER_ADMIN] => webmaster@localhost 
[SCRIPT_FILENAME] => /home/homer/workspace/proxy_client/test/test_proxy2.php 
[REMOTE_PORT] => 56336 
[GATEWAY_INTERFACE] => CGI/1.1 
[SERVER_PROTOCOL] => HTTP/1.1 
[REQUEST_METHOD] => GET 
[QUERY_STRING] => 
[REQUEST_URI] => /proxy_client/test/test_proxy2.php 
[SCRIPT_NAME] => /proxy_client/test/test_proxy2.php 
[PHP_SELF] => /proxy_client/test/test_proxy2.php 
[REQUEST_TIME_FLOAT] => 1422193664.933 
[REQUEST_TIME] => 1422193664 
)

 

---------------------------

为了保护网站的资源,我们通常会不允许代理访问我们的网站,以下方法可以过滤掉所有匿名代理与透明代理,但不能过滤超级代理,同时他们过滤掉局域网 的代理,所以如果要正常使用,可能还要做些必要的修改!

$proxy = 0;
if($_SERVER['HTTP_VIA'] != “”)
       { $proxy = 1; }
if($_SERVER['HTTP_X_FORWARDED_FOR'] != “”)
       { $proxy = 1; }
if($_SERVER['VIA'] != “”)
       { $proxy = 1; }
if($_SERVER['HTTP_FORWARDED'] != “”)
       { $proxy = 1; }
if($_SERVER['FORWARDED'] != “”)
       { $proxy = 1; }
if($_SERVER['HTTP_X_BLUECOAT_VIA'] != “”)
       { $proxy = 1; }
if($_SERVER['HTTP_PROXY____'] != “”)
       { $proxy = 1; }
if($_SERVER['HTTP_PROXY___________'] != “”)
       { $proxy = 1; }
if($_SERVER['HTTP_PROXY_CONNECTION'] != “”)
       { $proxy = 1; }
if($_SERVER['HTTP_X_HOST'] != “”)
       { $proxy = 1; }
if($_SERVER['HTTP_X_REFERER'] != “”)
       { $proxy = 1; }
if($_SERVER['HTTP_X_SERVER_HOSTNAME'] != “”)
       { $proxy = 1; }
if($_SERVER['PROXY_HOST'] != “”)
       { $proxy = 1; }
if($_SERVER['PROXY_PORT'] != “”)
       { $proxy = 1; }
if($_SERVER['PROXY_REQUEST'] != “”)
       { $proxy = 1; }
if($_SERVER['HTTP_CLIENT_IP'] != “”)
       { $proxy = 1; }
if($_SERVER['HTTP_PRAGMA'] != “”)
       { $proxy = 1; }

 

补充:

代理检测需要了解的基础知识,REMOTE_ADDR,HTTP_CLIENT_IP,HTTP_X_FORWARDED_FOR 这三个值是否存在。

1) REMOTE_ADDR 是你的客户端跟你的服务器“握手”时候的IP。如果使用了“匿名代理”,REMOTE_ADDR将显示代理服务器的IP。 此值一般是可靠的(相对伪造头信息而言),它可能是你真实的IP,也可能是代理的IP

2) HTTP_CLIENT_IP 是代理服务器发送的HTTP头。如果是“超级匿名代理”,则返回无此值。

3) HTTP_X_FORWARDED_FOR 是有标准定义,用来识别经过HTTP代理后的客户端IP地址,格式:clientip,proxy1,proxy2。详细解释见 http://zh.wikipedia.org/wiki/X-Forwarded-For

$_SERVER['REMOTE_ADDR'];          // 访问端IP,有可能是用户的IP(无代理) ,有可能是代理的IP(透明,匿名,高匿
$_SERVER['HTTP_CLIENT_IP'];        // 代理端的IP,有可能存在(透明,匿名),可有可能伪造(欺骗代理
$_SERVER['HTTP_X_FORWARDED_FOR'];   // 用户是在哪个IP使用的代理,有可能存在(透明,匿名),也可以伪造(欺骗代理

 

代理服务器分为:透明代理,匿名代理,高匿名代理

透明代理会将客户端的请求IP包含在HTTP头中,具体就是$_SERVER['HTTP_X_FORWARDED_FOR']中

匿名代理将客户端的IP隐藏起来,IP信息只能在$_SERVER['REMOTE_ADDR']中

一、没有使用代理服务器的情况

REMOTE_ADDR = 您的 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示

如果 REMOTE_ADDR 不是你真实的IP,则一定是使用了代理,各代理匿名度规则如下:

二、使用透明代理服务器的情况(Transparent Proxies)

REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 您的真实 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

这类代理服务器还是将您的真实IP信息转发给您的访问对象,无法达到隐藏真实身份的目的。

三、使用普通匿名代理服务器的情 况(Anonymous Proxies)

REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 代理服务器 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

隐藏了您的真实IP,但是向访问对象透露了您是使用代理服务器访问他们的。

四、使用欺骗性代理服务器的情 况(Distorting Proxies)

REMOTE_ADDR = 代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 随机的 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

告诉了访问对象您使用了代理服务器,但编造了一个虚假的随机IP代替您的真实IP欺骗它。

五、使用高匿名代理服务器 的情况(High Anonymity Proxies (Elite proxies))

REMOTE_ADDR = 代理服务器 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示 ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

完全用代理服务器的信息替代了您的所有信息,就象您就是完全使用那台代理服务器直接访问对象。

代码示例:

if(!empty($_SERVER['HTTP_VIA']))    //使用了代理
{
    if(!isset($_SERVER['HTTP_X_FORWARDED_FOR']))
    {
        //Anonymous Proxies    普通匿名代理服务器
        //代理IP地址为 $_SERVER['REMOTE_ADDR']
   }
   else
   {
        //Transparent Proxies 透明代理服务器
        //代理IP地址为 $_SERVER['REMOTE_ADDR']
        //真实ip地址为 $_SERVER['HTTP_X_FORWARDED_FOR']
   }
}
else    //没有代理或者是高匿名代理
{
    //真实ip地址为 $_SERVER['REMOTE_ADDR']
}

 

Nginx做代理后PHP取不到HTTP_X_FORWARDED_FOR值

原因 nginx 默认并不会增加 X_FORWARDED_FOR 头信息,我们给他加上就好了。简单配置如下:

  1. location /   
  2. {   
  3.     proxy_pass          http://www.92csz.com;   
  4.     proxy_set_header    Host             $host;   
  5.     proxy_set_header    X-Real-IP        $remote_addr;   
  6.     proxy_set_header    X-Forwarded-For  $proxy_add_x_forwarded_for;    //别忘了这一句   
  7.     proxy_set_header    HTTP_X_FORWARDED_FOR $remote_addr;              //或是加上这一句   
  8.     proxy_redirect      default;   
  9. }  

重启nginx加载新配置后,就可以获取客户端真实的IP地址了。

 

参考推荐

PHP中$_SERVER的详细用法

PHP中HTTP_X_FORWARDED_FOR

各种脚本语言获取客户端真实IP的方法

Python 代理验证及网页抓取

X-Forwarded-Forwikipedia 推荐

APACHE的代理扩展模块-mod_extract_forwarded

Forward Connections from Nginx to httpd in CentOS