From 29b217cf219a7f8f4dec569071a699fa8a44b6c2 Mon Sep 17 00:00:00 2001 From: nyro Date: Tue, 25 Nov 2014 17:19:30 +0100 Subject: [PATCH] [HttpKernel] Fix UriSigner::check when _hash is not at the end of the uri --- .../HttpKernel/Tests/UriSignerTest.php | 2 + .../Component/HttpKernel/UriSigner.php | 41 ++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Tests/UriSignerTest.php b/src/Symfony/Component/HttpKernel/Tests/UriSignerTest.php index 8ffc2bfbbd..b66014d849 100644 --- a/src/Symfony/Component/HttpKernel/Tests/UriSignerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/UriSignerTest.php @@ -33,5 +33,7 @@ class UriSignerTest extends \PHPUnit_Framework_TestCase $this->assertTrue($signer->check($signer->sign('http://example.com/foo'))); $this->assertTrue($signer->check($signer->sign('http://example.com/foo?foo=bar'))); + + $this->assertTrue($signer->sign('http://example.com/foo?foo=bar&bar=foo') === $signer->sign('http://example.com/foo?bar=foo&foo=bar')); } } diff --git a/src/Symfony/Component/HttpKernel/UriSigner.php b/src/Symfony/Component/HttpKernel/UriSigner.php index 199116b4c6..0f49487f05 100644 --- a/src/Symfony/Component/HttpKernel/UriSigner.php +++ b/src/Symfony/Component/HttpKernel/UriSigner.php @@ -42,6 +42,15 @@ class UriSigner */ public function sign($uri) { + $url = parse_url($uri); + if (isset($url['query'])) { + parse_str($url['query'], $params); + } else { + $params = array(); + } + + $uri = $this->buildUrl($url, $params); + return $uri.(false === (strpos($uri, '?')) ? '?' : '&').'_hash='.$this->computeHash($uri); } @@ -58,15 +67,43 @@ class UriSigner */ public function check($uri) { - if (!preg_match('/^(.*)(?:\?|&)_hash=(.+?)$/', $uri, $matches)) { + $url = parse_url($uri); + if (isset($url['query'])) { + parse_str($url['query'], $params); + } else { + $params = array(); + } + + if (empty($params['_hash'])) { return false; } - return $this->computeHash($matches[1]) === $matches[2]; + $hash = urlencode($params['_hash']); + unset($params['_hash']); + + return $this->computeHash($this->buildUrl($url, $params)) === $hash; } private function computeHash($uri) { return urlencode(base64_encode(hash_hmac('sha1', $uri, $this->secret, true))); } + + private function buildUrl(array $url, array $params = array()) + { + ksort($params); + $url['query'] = http_build_query($params); + + $scheme = isset($url['scheme']) ? $url['scheme'].'://' : ''; + $host = isset($url['host']) ? $url['host'] : ''; + $port = isset($url['port']) ? ':'.$url['port'] : ''; + $user = isset($url['user']) ? $url['user'] : ''; + $pass = isset($url['pass']) ? ':'.$url['pass'] : ''; + $pass = ($user || $pass) ? "$pass@" : ''; + $path = isset($url['path']) ? $url['path'] : ''; + $query = isset($url['query']) && $url['query'] ? '?'.$url['query'] : ''; + $fragment = isset($url['fragment']) ? '#'.$url['fragment'] : ''; + + return $scheme.$user.$pass.$host.$port.$path.$query.$fragment; + } }