diff --git a/README.md b/README.md index 4ef8f16..6eda57a 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,7 @@ You can donate any amount of your choice by [clicking here](https://www.paypal.c - [Custom EventHandlers](#custom-eventhandlers) - [Advanced](#advanced) - [Disable multiple route rendering](#disable-multiple-route-rendering) + - [Restrict access to IP](#restrict-access-to-ip) - [Url rewriting](#url-rewriting) - [Changing current route](#changing-current-route) - [Bootmanager: loading routes dynamically](#bootmanager-loading-routes-dynamically) @@ -1370,6 +1371,31 @@ By default the router will try to execute all routes that matches a given url. T This behavior can be easily disabled by setting `SimpleRouter::enableMultiRouteRendering(false)` in your `routes.php` file. This is the same behavior as version 3 and below. +## Restrict access to IP + +You can white- and blacklist access to IP's using the build in `IpBlockAccess` middleware. + +Create your own Middleware and extend the `IpBlockAccess` class. + +You can use `*` to restrict access to a range of ips. + +```php +use \Pecee\Http\Middleware\IpBlockAccess; + +class IpBlockMiddleware extends IpBlockAccess { + + protected $ipBlacklist = [ + '5.5.5.5', + '8.8.*', + ]; + + protected $ipWhitelist = [ + '8.8.2.2', + ]; + +} +``` + ## Url rewriting ### Changing current route diff --git a/src/Pecee/Http/Middleware/IpBlockAccess.php b/src/Pecee/Http/Middleware/IpBlockAccess.php new file mode 100644 index 0000000..f19d821 --- /dev/null +++ b/src/Pecee/Http/Middleware/IpBlockAccess.php @@ -0,0 +1,43 @@ +ipWhitelist, true) === true) { + return true; + } + + foreach ($this->ipBlacklist as $blackIp) { + + // Blocks range (8.8.*) + if ($blackIp[strlen($blackIp) - 1] === '*' && strpos($ip, trim($blackIp, '*')) === 0) { + return false; + } + + // Blocks exact match + if ($blackIp === $ip) { + return false; + } + + } + + return true; + } + + public function handle(Request $request): void + { + if($this->validate((string)$request->getIp()) === false) { + throw new HttpException(sprintf('Restricted ip. Access to %s has been blocked', $request->getIp()), 403); + } + } +} \ No newline at end of file diff --git a/tests/Pecee/SimpleRouter/CustomMiddlewareTest.php b/tests/Pecee/SimpleRouter/CustomMiddlewareTest.php new file mode 100644 index 0000000..bf19094 --- /dev/null +++ b/tests/Pecee/SimpleRouter/CustomMiddlewareTest.php @@ -0,0 +1,71 @@ +expectException(\Pecee\SimpleRouter\Exceptions\HttpException::class); + + global $_SERVER; + + // Test exact ip + + $_SERVER['remote-addr'] = '5.5.5.5'; + + TestRouter::group(['middleware' => IpBlockMiddleware::class], function() { + TestRouter::get('/fail', 'DummyController@method1'); + }); + + TestRouter::debug('/fail'); + + // Test ip-range + + $_SERVER['remote-addr'] = '8.8.4.4'; + + TestRouter::router()->reset(); + + TestRouter::group(['middleware' => IpBlockMiddleware::class], function() { + TestRouter::get('/fail', 'DummyController@method1'); + }); + + TestRouter::debug('/fail'); + + } + + public function testIpSuccess() { + + global $_SERVER; + + // Test ip that is not blocked + + $_SERVER['remote-addr'] = '6.6.6.6'; + + TestRouter::router()->reset(); + + TestRouter::group(['middleware' => IpBlockMiddleware::class], function() { + TestRouter::get('/success', 'DummyController@method1'); + }); + + TestRouter::debug('/success'); + + // Test ip in whitelist + + $_SERVER['remote-addr'] = '8.8.2.2'; + + TestRouter::router()->reset(); + + TestRouter::group(['middleware' => IpBlockMiddleware::class], function() { + TestRouter::get('/success', 'DummyController@method1'); + }); + + TestRouter::debug('/success'); + + $this->assertTrue(true); + + } + +} \ No newline at end of file diff --git a/tests/Pecee/SimpleRouter/Dummy/Middleware/IpBlockMiddleware.php b/tests/Pecee/SimpleRouter/Dummy/Middleware/IpBlockMiddleware.php new file mode 100644 index 0000000..ee525cf --- /dev/null +++ b/tests/Pecee/SimpleRouter/Dummy/Middleware/IpBlockMiddleware.php @@ -0,0 +1,14 @@ +