├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── preview.png └── src ├── Http └── Middleware │ └── SiteProtection.php ├── SiteProtectionServiceProvider.php ├── config └── site-protection.php └── views └── site-protection-form.blade.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | composer.lock 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Matthias Lill 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Very simple site wide password protection for Laravel5 2 | 3 | This will add a simple password form in front of your application to protected it 4 | from any access. The password is specified using the `.env` file to protect DEV 5 | or STAGE sites only. 6 | 7 | You can use multiple passwords for different user groups. Once the password is 8 | removed, the access is revoked. 9 | 10 | This does not protect any assets files like css or images. 11 | 12 | __Looks like__ 13 | 14 |  15 | 16 | ## Installation 17 | 18 | ``` 19 | composer require elic-dev/laravel-site-protection 20 | ``` 21 | 22 | ### Laravel >= 5.2 23 | 24 | This package requires at least the Laravel Framework of version **5.2**. 25 | 26 | Add ServiceProvider to the providers array in `app/config/app.php`. 27 | 28 | ``` 29 | ElicDev\SiteProtection\SiteProtectionServiceProvider::class, 30 | ``` 31 | 32 | ### Laravel >= 5.5 33 | 34 | You don't need to add this package to your `app/config/app.php` since it supports auto discovery. 35 | 36 | ### Add Middleware (Laravel < 11.0) 37 | 38 | Add Middleware to `app/Http/Kernel.php` or specific routes you want to protect. 39 | 40 | ``` 41 | protected $middlewareGroups = [ 42 | 'web' => [ 43 | ... 44 | \ElicDev\SiteProtection\Http\Middleware\SiteProtection::class, 45 | ], 46 | ... 47 | ]; 48 | ``` 49 | 50 | ### Add Middleware (Laravel >= 11.0) 51 | 52 | Edit Middleware at `config/app.php` and include against the 'web' middleware. 53 | 54 | ``` 55 | ->withMiddleware(function (Middleware $middleware) { 56 | $middleware->appendToGroup('web',\ElicDev\SiteProtection\Http\Middleware\SiteProtection::class); 57 | }) 58 | ``` 59 | 60 | ### Configuration 61 | 62 | Most configuration can be done using ENV variables by adding the following keys 63 | to your `.env` file. 64 | 65 | #### Adjusting the passwords 66 | 67 | You can use multiple passwords separated by comma. 68 | 69 | ``` 70 | SITE_PROTECTION_PASSWORDS=password1,password2 71 | ``` 72 | 73 | To revoke access to your site simply change the password. This requires every 74 | user using the old password to re-enter a password. 75 | 76 | #### Exclude certain paths from protection 77 | 78 | You can exclude specific paths from protection. Add a comma seperated list of paths to your 79 | `.env` file. You can use the `*` to exclude a group of paths. 80 | 81 | ``` 82 | SITE_PROTECTION_EXCEPT_PATHS=path1,path2,login* 83 | ``` 84 | 85 | #### Protect only specific paths 86 | 87 | You can protect only some paths. Add a comma seperated list of paths to your 88 | `.env` file. You can use the `*` to protect a a group of paths. 89 | 90 | ``` 91 | SITE_PROTECTION_PROTECTED_ONLY_PATHS=path1,path2,admin* 92 | ``` 93 | 94 | #### Set a CSS file uri 95 | 96 | You can change the look and feel of the password protection page by adding an uri 97 | to your main css file. The css file is appened to the existing css styles to keep 98 | basic alignments. 99 | 100 | ``` 101 | SITE_PROTECTION_CSS_FILE_URI=/assets/app.css 102 | ``` 103 | 104 | #### Cookie lifetime 105 | 106 | Set the duration for the cookie lifetime in seconds. Default is set to one year. 107 | The following `.env` value would change it to one week: 108 | 109 | ``` 110 | SITE_PROTECTION_COOKIE_LIFETIME=604800 111 | ``` 112 | 113 | ### Customization 114 | 115 | In case you really need to. You can modify the view that handles password entry by publishing the views to your 116 | resource folder. This is not recommended and might cause problems on future updates. Try using the uri to a css 117 | file first. 118 | 119 | Run the following command: 120 | 121 | ``` 122 | php artisan vendor:publish --provider="ElicDev\SiteProtection\SiteProtectionServiceProvider" --tag=views 123 | ``` 124 | 125 | You can now make the changes in `resources/vendor/views/site-protection/site-protection-form.blade.php`. 126 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "elic-dev/laravel-site-protection", 3 | "description": "Protect your site with a simple password form", 4 | "type": "library", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Matthias Lill", 9 | "email": "m.lill@gmx.de" 10 | } 11 | ], 12 | "require": { 13 | "php": ">=5.6.4" 14 | }, 15 | "autoload": { 16 | "psr-4": { 17 | "ElicDev\\SiteProtection\\": "src/" 18 | } 19 | }, 20 | "extra": { 21 | "laravel": { 22 | "providers": [ 23 | "ElicDev\\SiteProtection\\SiteProtectionServiceProvider" 24 | ] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elic-dev/laravel-site-protection/408ba4993b9fb44e63a9994a8c9dfd964952fd4f/preview.png -------------------------------------------------------------------------------- /src/Http/Middleware/SiteProtection.php: -------------------------------------------------------------------------------- 1 | inExceptArray($request) || 26 | $this->isNotInProtectedOnlyPath($request)) { 27 | return $next($request); 28 | } 29 | 30 | $passwords = explode(',', $password); 31 | 32 | if (in_array($request->get('site-password-protected'), $passwords)) { 33 | setcookie('site-password-protected', encrypt($request->get('site-password-protected')), time() + config('site-protection.cookie_lifetime'), '/'); 34 | return redirect($request->url()); 35 | } 36 | 37 | try { 38 | $usersPassword = decrypt(Arr::get($_COOKIE, 'site-password-protected')); 39 | if (in_array($usersPassword, $passwords)) { 40 | return $next($request); 41 | } 42 | } catch (DecryptException $e) { 43 | // empty value in cookie 44 | } 45 | 46 | return response(view('site-protection::site-protection-form'), 403); 47 | } 48 | 49 | /** 50 | * Determine if the request has a URI is only protect. 51 | * 52 | * @param \Illuminate\Http\Request $request 53 | * @return bool 54 | */ 55 | protected function isNotInProtectedOnlyPath($request) 56 | { 57 | $protectOnlyPaths = config('site-protection.protected_only_paths'); 58 | 59 | if (empty($protectOnlyPaths)) { 60 | return false; 61 | } 62 | 63 | if (is_string($protectOnlyPaths)) { 64 | $protectOnlyPaths = explode(',', $protectOnlyPaths); 65 | } 66 | 67 | foreach ($protectOnlyPaths as $except) { 68 | if ($except !== '/') { 69 | $except = trim($except, '/'); 70 | } 71 | 72 | if ($request->fullUrlIs($except) || $request->is($except)) { 73 | return false; 74 | } 75 | } 76 | 77 | return true; 78 | } 79 | 80 | 81 | /** 82 | * Determine if the request has a URI that should pass through SiteProtection. 83 | * 84 | * @param \Illuminate\Http\Request $request 85 | * @return bool 86 | */ 87 | protected function inExceptArray($request) 88 | { 89 | $exceptedPaths = config('site-protection.except_paths'); 90 | 91 | if (empty($exceptedPaths)) { 92 | return false; 93 | } 94 | 95 | if (is_string($exceptedPaths)) { 96 | $exceptedPaths = explode(',', $exceptedPaths); 97 | } 98 | 99 | foreach ($exceptedPaths as $except) { 100 | if ($except !== '/') { 101 | $except = trim($except, '/'); 102 | } 103 | 104 | if ($request->fullUrlIs($except) || $request->is($except)) { 105 | return true; 106 | } 107 | } 108 | 109 | return false; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/SiteProtectionServiceProvider.php: -------------------------------------------------------------------------------- 1 | mergeConfigFrom( 17 | __DIR__ . '/config/site-protection.php', 'site-protection' 18 | ); 19 | } 20 | 21 | /** 22 | * Bootstrap the application services. 23 | * 24 | * @return void 25 | */ 26 | public function boot() 27 | { 28 | $this->loadViewsFrom(__DIR__ . '/views', 'site-protection'); 29 | 30 | $this->publishes([ 31 | __DIR__ . '/views' => resource_path('views/vendor/site-protection'), 32 | ], 'views'); 33 | 34 | $this->publishes([ 35 | __DIR__ . '/config' => config_path(), 36 | ], 'config'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/config/site-protection.php: -------------------------------------------------------------------------------- 1 | env('SITE_PROTECTION_PASSWORDS'), 16 | 17 | /* 18 | |-------------------------------------------------------------------------- 19 | | Except certain paths 20 | |-------------------------------------------------------------------------- 21 | | 22 | | 23 | | 24 | | 25 | */ 26 | 27 | 'except_paths' => env('SITE_PROTECTION_EXCEPT_PATHS'), 28 | 29 | /* 30 | |-------------------------------------------------------------------------- 31 | | Protect only specific paths 32 | |-------------------------------------------------------------------------- 33 | | 34 | | 35 | | 36 | | 37 | */ 38 | 39 | 'protected_only_paths' => env('SITE_PROTECTION_PROTECTED_ONLY_PATHS'), 40 | 41 | /* 42 | |-------------------------------------------------------------------------- 43 | | Simple path to a CSS file 44 | |-------------------------------------------------------------------------- 45 | | 46 | | 47 | | 48 | | 49 | */ 50 | 51 | 'css_file_uri' => env('SITE_PROTECTION_CSS_FILE_URI'), 52 | 53 | /* 54 | |-------------------------------------------------------------------------- 55 | | Cookie lifetime 56 | |-------------------------------------------------------------------------- 57 | | 58 | | 59 | | 60 | | 61 | */ 62 | 63 | 'cookie_lifetime' => env('SITE_PROTECTION_COOKIE_LIFETIME', 365*24*60*60), 64 | ]; 65 | -------------------------------------------------------------------------------- /src/views/site-protection-form.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |