
そのままでは動作しませんが、参考までにどうぞ。
もくじ
条件
クライアントIPを判別してLaravel側のログインページのアクセスを制限する機能をつくります。
- クライアント -> CloudFront -> ELB -> Nginx(Laravel)
テーブルの作成
- 機能有効化フラグを設定
admins.is_access_control_enabled - 許可IPを設定
admin_allowed_ips.allowed_ip
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
/**
* Class CreateAdminsTable.
*/
class CreateAdminsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
if (!Schema::hasTable('admins')) {
Schema::create('admins', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name')->nullable();
$table->string('subdomain');
$table->boolean('is_access_control_enabled')->default(false)->comment('IP制限機能が有効か?')
$table->timestamps();
$table->unique('hostname');
});
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('admins');
}
}
database/migrations/2021_02_19_135616_create_admin_allowed_ips.php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateAdminAllowedIps extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
const TABLE_NAME = "admin_allowed_ips";
public function up()
{
if (Schema::hasTable(self::TABLE_NAME)) {
return;
}
Schema::create(self::TABLE_NAME, function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('admin_id')->unsigned();
$table->string('allowed_ip')->comment('アクセス許可IP');
$table->timestamps();
$table->foreign('admin_id', 'aai_idfk_admins')
->references('id')
->on('admins')
->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table(self::TABLE_NAME, function (Blueprint $table) {
$table->dropForeign('aai_idfk_admins');
});
Schema::drop(self::TABLE_NAME);
}
}
Entity
app/Entities/AdminAllowedIp
namespace App\Entities;
use Illuminate\Database\Eloquent\Model;
use Prettus\Repository\Contracts\Transformable;
use Prettus\Repository\Traits\TransformableTrait;
/**
* Class AdminAllowedIp.
*
* @package namespace App\Entities;
*/
class AdminAllowedIp extends Model implements Transformable
{
use TransformableTrait;
protected $guarded = [
'id'
];
public function admin()
{
return $this->belongsTo('App\Entities\Admin');
}
}
Repository
app/Repositories/Admin/AdminAllowedIpInterface
namespace App\Repositories\Admin;
use App\Repositories\Traits\ResourceConstructInterface;
interface AdminAllowedIpInterface extends ResourceConstructInterface
{
//
}
app/Repositories/Admin/AdminAllowedIpRepository
namespace App\Repositories\Admin;
use App\Entities\AdminAllowedIp;
use App\Repositories\Admin\AdminAllowedIpInterface;
use App\Repositories\Traits\ResourceConstructTrait;
class AdminAllowedIpRepository implements AdminAllowedIpInterface
{
use ResourceConstructTrait;
public function __construct(AdminAllowedIp $resource)
{
$this->resource = $resource;
}
}
バインド
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
//
}
/**
* Register services.
*
* @return void
*/
public function register()
{
・・・
$this->app->bind(
\App\Repositories\Admin\AdminAllowedIpInterface::class,
\App\Repositories\Admin\AdminAllowedIpRepository::class
);
・・・
}
}
ミドルウェアの作成
App\Http\Middleware\AllowedIpCheck.php
namespace App\Http\Middleware;
use Closure;
// 管理画面 IP制限ミドルウェア
class AllowedIpCheck
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
list($subdomain, $domain, $route_domain) = (explode('.', $_SERVER['HTTP_Host']));
// get id by subdomain
$Admin = app()->make(\App\Repositories\Admin\AdminRepository::class)->findWhere([
'subdomain' => $subdomain,
]);
if (is_null($Admin)) {
throw new \Symfony\Component\HttpKernel\Exception\NotFoundHttpException("対象の管理者が見つかりません");
}
// IP制限が有効か?
if (!$admin->is_access_control_enabled) {
return $next($request);
}
// AWS固有のIP格納ヘッダーの有無チェック
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
// 1番目にデバイスIP, 2番目にCloudFront IP
list($device_ip, $cloud_front_ip) = ($_SERVER['HTTP_X_FORWARDED_FOR'] === '') ? array() : explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); // ex. 153.xxx.xxx.1, 130.176.135.157
// 許可IPを配列で取得
$allowed_ips = app()->make(\App\Repositories\Admin\AdminAllowedIpRepository::class)->byWhere([
'admin_id' => $admin->id,
])->pluck('allowed_ip')->toArray();
// 許可IP確認
if (array_search($device_ip, $allowed_ips) === false) {
throw new \Symfony\Component\HttpKernel\Exception\NotFoundHttpException("アクセスが許可されていません");
}
}
return $next($request);
}
}
Kernelにミドルウェアを登録
app/Http/Kernel.php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
use App\Http\Middleware\UA\SetLocale;
use App\Http\Middleware\UA\ResponseJsonFormatter;
class Kernel extends HttpKernel
{
・・・
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
'admin_allowed_ip_check' => \App\Http\Middleware\AllowedIpCheck::class,
];
}
Routeに設定
ログイン画面にIP制限をかけます。
routes/admin.php
// IP制限ミドルウェア
Route::group(['middleware' => ['admin_allowed_ip_check']], function () {
// 認証不要
Route::get('/', function () {
return view('ADMIN.login.index');
});
Route::group(['prefix' => 'login'], function () {
Route::get('/', function () {
return view('ADMIN.login.index');
})->name('ADMIN.login.index');
});
});
・・・
$ composer dumpa $ php artisan route:clear

