diff --git a/src/Illuminate/Cache/RateLimiter.php b/src/Illuminate/Cache/RateLimiter.php index efa83d4fc01c..388b430236c3 100644 --- a/src/Illuminate/Cache/RateLimiter.php +++ b/src/Illuminate/Cache/RateLimiter.php @@ -36,6 +36,8 @@ public function __construct(Cache $cache) */ public function tooManyAttempts($key, $maxAttempts) { + $key = $this->cleanRateLimiterKey($key); + if ($this->attempts($key) >= $maxAttempts) { if ($this->cache->has($key.':timer')) { return true; @@ -56,6 +58,8 @@ public function tooManyAttempts($key, $maxAttempts) */ public function hit($key, $decaySeconds = 60) { + $key = $this->cleanRateLimiterKey($key); + $this->cache->add( $key.':timer', $this->availableAt($decaySeconds), $decaySeconds ); @@ -79,6 +83,8 @@ public function hit($key, $decaySeconds = 60) */ public function attempts($key) { + $key = $this->cleanRateLimiterKey($key); + return $this->cache->get($key, 0); } @@ -90,6 +96,8 @@ public function attempts($key) */ public function resetAttempts($key) { + $key = $this->cleanRateLimiterKey($key); + return $this->cache->forget($key); } @@ -102,6 +110,8 @@ public function resetAttempts($key) */ public function retriesLeft($key, $maxAttempts) { + $key = $this->cleanRateLimiterKey($key); + $attempts = $this->attempts($key); return $maxAttempts - $attempts; @@ -115,6 +125,8 @@ public function retriesLeft($key, $maxAttempts) */ public function clear($key) { + $key = $this->cleanRateLimiterKey($key); + $this->resetAttempts($key); $this->cache->forget($key.':timer'); @@ -128,6 +140,19 @@ public function clear($key) */ public function availableIn($key) { + $key = $this->cleanRateLimiterKey($key); + return $this->cache->get($key.':timer') - $this->currentTime(); } + + /** + * Clean the rate limiter key from unicode characters. + * + * @param string $key + * @return string + */ + public function cleanRateLimiterKey($key) + { + return preg_replace('/&([a-z])[a-z]+;/i', '$1', htmlentities($key)); + } } diff --git a/tests/Cache/CacheRateLimiterTest.php b/tests/Cache/CacheRateLimiterTest.php index f0d9236da0cb..11b48382e0c8 100644 --- a/tests/Cache/CacheRateLimiterTest.php +++ b/tests/Cache/CacheRateLimiterTest.php @@ -66,4 +66,15 @@ public function testClearClearsTheCacheKeys() $rateLimiter->clear('key'); } + + public function testKeysAreSanitizedFromUnicodeCharacters() + { + $cache = m::mock(Cache::class); + $cache->shouldReceive('get')->once()->with('john', 0)->andReturn(1); + $cache->shouldReceive('has')->once()->with('john:timer')->andReturn(true); + $cache->shouldReceive('add')->never(); + $rateLimiter = new RateLimiter($cache); + + $this->assertTrue($rateLimiter->tooManyAttempts('jôhn', 1)); + } }