Skip to content

Commit

Permalink
Allow specifying proxy header to use
Browse files Browse the repository at this point in the history
- Adds setProxyHeader static method, allowing developer to specify which
  header to use when testing for proxies
  - By default uses X-Forwarded-For
  - Normalizes header string name to work with $_SERVER
  • Loading branch information
weierophinney committed Nov 29, 2012
1 parent cfaf5ea commit ad8fdc3
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 4 deletions.
44 changes: 41 additions & 3 deletions library/Zend/Session/Validator/RemoteAddr.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ class RemoteAddr implements SessionValidator
*/
protected static $trustedProxies = array();

/**
* HTTP header to introspect for proxies
*
* @var string
*/
protected static $proxyHeader = 'HTTP_X_FORWARDED_FOR';

/**
* Constructor
* get the current user IP and store it in the session as 'valid data'
Expand Down Expand Up @@ -103,6 +110,17 @@ public static function setTrustedProxies(array $trustedProxies)
static::$trustedProxies = $trustedProxies;
}

/**
* Set the header to introspect for proxy IPs
*
* @param string $header
* @return void
*/
public static function setProxyHeader($header = 'X-Forwarded-For')
{
static::$proxyHeader = static::normalizeProxyHeader($header);
}

/**
* Returns client IP address.
*
Expand Down Expand Up @@ -134,13 +152,14 @@ protected function getIpAddressFromProxy()
return false;
}

// Only ever look at X-Forwarded-For header; Client-IP is unreliable
if (!isset($_SERVER['HTTP_X_FORWARDED_FOR']) || empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$header = static::$proxyHeader;

if (!isset($_SERVER[$header]) || empty($_SERVER[$header])) {
return false;
}

// Extract IPs
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$ips = explode(',', $_SERVER[$header]);
// trim, so we can compare against trusted proxies properly
$ips = array_map('trim', $ips);
// remove trusted proxy IPs
Expand Down Expand Up @@ -175,4 +194,23 @@ public function getName()
{
return __CLASS__;
}

/**
* Normalize a header string
*
* Normalizes a header string to a format that is compatible with
* $_SERVER
*
* @param string $header
* @return string
*/
protected static function normalizeProxyHeader($header)
{
$header = strtoupper($header);
$header = str_replace('-', '_', $header);
if (0 !== strpos($header, 'HTTP_')) {
$header = 'HTTP_' . $header;
}
return $header;
}
}
17 changes: 16 additions & 1 deletion tests/ZendTest/Session/Validator/RemoteAddrTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@ protected function backup()
);
RemoteAddr::setUseProxy(false);
RemoteAddr::setTrustedProxies(array());
RemoteAddr::setProxyHeader();
}

protected function restore()
{
$_SERVER = $this->backup;
RemoteAddr::setUseProxy(false);
RemoteAddr::setTrustedProxies(array());
RemoteAddr::setProxyHeader();
}

public function testGetData()
Expand Down Expand Up @@ -115,7 +117,7 @@ public function testUsesRightMostAddressWhenMultipleHttpXForwardedForAddressesPr
$this->restore();
}

public function testShouldNotUseClientIpHeaderToTestProxyCapabilities()
public function testShouldNotUseClientIpHeaderToTestProxyCapabilitiesByDefault()
{
$this->backup();
$_SERVER['REMOTE_ADDR'] = '0.1.2.3';
Expand All @@ -138,4 +140,17 @@ public function testWillOmitTrustedProxyIpsFromXForwardedForMatching()
$this->assertEquals('2.1.2.3', $validator->getData());
$this->restore();
}

public function testCanSpecifyWhichHeaderToUseStatically()
{
$this->backup();
$_SERVER['REMOTE_ADDR'] = '0.1.2.3';
$_SERVER['HTTP_X_FORWARDED_FOR'] = '2.1.2.3, 1.1.2.3';
$_SERVER['HTTP_CLIENT_IP'] = '0.1.2.4';
RemoteAddr::setUseProxy(true);
RemoteAddr::setProxyHeader('Client-Ip');
$validator = new RemoteAddr();
$this->assertEquals('0.1.2.4', $validator->getData());
$this->restore();
}
}

0 comments on commit ad8fdc3

Please sign in to comment.