获取客户端IP用什么方式?
在这个灌水盛行的年代,我们必须要对那些心怀不轨,总是想着做点啥坏事的青年们,致以亲切的祝福:最近还好吗,是不是闲的蛋疼。
本博客使用Typecho 程序搭建,添加验证码插件后,垃圾评论还是有不少。隔个5-6天就有20多条,前几天修正了验证码插件当中的一个bug,稍微减缓了一点,不过还是有一些。这里就再对后台 “同一IP发布评论的时间间隔限制为N分钟”这个功能动点手脚吧。首先要说明的是,这个功能并不能阻挡这些“灌水青年”的恶劣行为,这是因为基于Typecho程序,这个IP可以伪造,致使上面的设置起不到作用。但是这并不能认为是Typecho的bug,因为当你了解了它的用意之后就会明白。
先来看看这段代码:var/Typecho/Request.php
/** * 设置ip地址 * * @access public * @param unknown $ip * @return unknown */ public function setIp($ip = NULL) { switch (true) { case NULL !== $this->getServer('HTTP_X_FORWARDED_FOR'): $this->_ip = $this->getServer('HTTP_X_FORWARDED_FOR'); return; case NULL !== $this->getServer('HTTP_CLIENT_IP'): $this->_ip = $this->getServer('HTTP_CLIENT_IP'); return; case NULL !== $this->getServer('REMOTE_ADDR'): $this->_ip = $this->getServer('REMOTE_ADDR'); return; default: break; } $this->_ip = 'unknown'; } /** * 获取ip地址 * * @access public * @return string */ public function getIp() { if (NULL === $this->_ip) { $this->setIp(); } return $this->_ip; }
通过getIp来获取,然后会调用setIp,所以在这里setIp是关键代码。通过上面setIp的代码可以了解到,程序会依次从 $_SERVER['HTTP_X_FORWARDED_FOR'],$_SERVER['HTTP_CLIENT_IP'],$_SERVER['REMOTE_ADDR'] 这上三个变量中获取客户端 IP 。但是在 $_SERVER['HTTP_XXX'] 这种格式的变量是客户端浏览器发送过来的,也就是可以伪造。
那为什么Typecho 程序员会写出这样的代码呢,你要相信他们的聪明才智,这么写是行业通用做法。那究竟作用在哪里呢?当运行Typecho程序的服务器与客户端浏览器之前还有一层代理服务器时,通过 $_SERVER['REMOTE_ADDR'] 获取到的IP不是客户端真正的IP地址,而是这层代理服务器的IP,所以为了兼容这种服务器架构,Typecho程序才这么写。
现在明白了吧,可以根据自己服务器的架构来优化这个代码,以达到防灌水的目的。如果服务器可以直接通过IP访问,那么可以像以下方式修改代码,否则慎重考虑,三思而后行。
public function setIp($ip = NULL) { switch (true) { case NULL !== $this->getServer('REMOTE_ADDR'): $this->_ip = $this->getServer('REMOTE_ADDR'); return; default: break; } $this->_ip = 'unknown'; }
如果有更好、更简便的方式,请您转告一声。