8
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Laravel5.6 ドメインルーティング+マルチ認証

8
Posted at

Laravel5.6 ドメインルーティング+マルチ認証

いじってる間にLaravel5.7が出てしまったけど5.6です。多分変わってないはず。

前提条件

  • Laravel5.6をcomposerでインストール済み
    composer create-project --prefer-dist laravel/laravel myapp "5.6.*"
  • DocumentRootはpublicディレクトリを指定。その他AllowOverride All等も適宜設定済み
    DocumentRoot "/var/www/html/myapp/public"
  • データベースを利用できるよう設定済み

やりたいこと

  • 接続時のドメインでフロントエンドとバックエンドに振り分ける
  • フロントエンドとバックエンドで異なるDBテーブルのユーザーで認証する
  • ログインIDはメールアドレスではなく独自で発行したものを使用する

※ユーザー登録、パスワードリセットは取り扱わない

マイグレーション

php artisan make:migration create_members_table
database/migrations/9999_99_99_create_members_table.php

    public function up()
    {
        Schema::create('members', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('loginid')->unique();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

create_admins_tableも同様に作成する。

マイグレーションを実行する

php artisan migrate

Eloquentモデルを作成

Illuminate\Database\Eloquent\ModelではなくIlluminate\Foundation\Auth\Userを継承する。

app/Member.php
<?php
namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;

class Member extends Authenticatable
{
    /** @var array */
    protected $fillable = [
        'name', 'loginid', 'password',
    ];

    /** @var array */
    protected $hidden = [
        'password', 'remember_token',
    ];
}

app/Admin.phpも同様に作成する。

ユーザーデータ作成

php artisan tinker 等で作成しておく。

>>> $member = App\Member::create(['name' => 'Tester', 'loginid' => 'tester', 'password' => Hash::make('password')]);
>>> $admin = App\Admin::create(['name' => 'Admin', 'loginid' => 'admin', 'password' => Hash::make('password')]);

認証設定

ガードとプロバイダーにフロントエンド用、バックエンド用を設定する。

config/auth.php
<?php

return [
    'defaults' => [
        'guard' => 'front',  // webは使用しないのでfrontに変更
        'passwords' => 'users',
    ],
    
    'guards' => [  // webを削除してfrontとbackを追加
        'front' => [
            'driver' => 'session',
            'provider' => 'members',
        ],

        'back' => [
            'driver' => 'session',
            'provider' => 'admins',
        ],

    ],

    'providers' => [  // 作成したEloquentモデルを指定
        'members' => [
            'driver' => 'eloquent',
            'model' => App\Member::class,
        ],

        'admins' => [
            'driver' => 'eloquent',
            'model' => App\Models\Admin::class,
        ],
    ],

ルーティング

ドメインでルーティングを分ける。フロントエンドとバックエンドのドメインを変えることでセッションCookieの競合も解決出来るので一石二鳥。
ここではlocalhost => App\Http\Controllers\Front, 127.0.0.1 => App\Http\Controllers\Back以下のコントローラーを利用するようにする。

routes/web.php

Route::group(['domain' => 'localhost', 'namespace' => 'Front'], function () {
    Route::get('/login', 'Auth\LoginController@showLoginForm');
    Route::post('/login', 'Auth\LoginController@login');
    Route::post('/logout', 'Auth\LoginController@logout');

    Route::middleware(['auth:front'])->group(function () {
        // 認証が必要な画面はこの下に記述
        Route::get('/home', 'HomeController@index');
    });
});

Route::group(['domain' => '127.0.0.1', 'namespace' => 'Back'], function () {
    Route::get('/login', 'Auth\LoginController@showLoginForm');
    Route::post('/login', 'Auth\LoginController@login');
    Route::post('/logout', 'Auth\LoginController@logout');

    Route::middleware(['auth:back'])->group(function () {
        // 認証が必要な画面はこの下に記述
        Route::get('/home', 'HomeController@index');
    });
});

未認証時のリダイレクト先を設定

デフォルトはroute('login')にリダイレクトするようになっているので調整する。

Handler->unauthenticatedを追加する。
バックエンドはログイン画面に、フロントエンドはトップにリダイレクトする。

app/Exceptions/Handler.php

    protected function unauthenticated($request, AuthenticationException $exception)
    {
        if ($request->expectsJson()) {
            return response()->json(['message' => $exception->getMessage()], 401);
        }
        if (in_array('back', $exception->guards())) {
            return redirect()->guest(url('/login'));
        }
        if (in_array('front', $exception->guards())) {
            return redirect()->guest(url('/'));
        }
        return redirect()->guest(url('/'));
    }

コントローラーの作成

ログイン画面

app/Http/Controllers/Front/Auth/LoginController.php
<?php

namespace App\Http\Controllers\Front\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
    use AuthenticatesUsers;

    /**
     * ログイン後に遷移する画面を設定する
     *
     * @var string
     */
    protected $redirectTo = '/home';

    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }

    /**
     * ログインIDに使用する項目を設定する
     *
     * @return string
     */
    public function username()
    {
        return 'loginid';
    }

    /**
     * 認証に使用するguardを設定する
     *
     * @return mixed
     */
    public function guard()
    {
        return Auth::guard('front');
    }
}

ログイン後に表示する画面

app/Http/Controllers/Front/HomeController.php
<?php

namespace App\Http\Controllers\Front;

use App\Http\Controllers\Controller;

class HomeController extends Controller
{
    public function index()
    {
        return view('home');
    }
}

Backも同様に作成する。

ビューの作成

php artisan make:authを実行した際に作成されるものを参考に適宜作成。

route('login')等の名前付きルートURLは使用せず、url('/login')等に置き換える。
※テンプレートを共用するための措置。分けるのであればルート側で適宜名前を付けてもよい。

resources/layouts/app.blade.php
内容は割愛
resources/views/auth/login.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Login') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ url('/login') }}" aria-label="{{ __('Login') }}">
                        @csrf

                        <div class="form-group row">
                            <label for="email" class="col-sm-4 col-form-label text-md-right">{{ __('Login ID') }}</label>

                            <div class="col-md-6">
                                <input id="loginid" type="text" class="form-control{{ $errors->has('loginid') ? ' is-invalid' : '' }}" name="loginid" value="{{ old('loginid') }}" required autofocus>

                                @if ($errors->has('loginid'))
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $errors->first('loginid') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>

                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" required>

                                @if ($errors->has('password'))
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $errors->first('password') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <div class="col-md-6 offset-md-4">
                                <div class="form-check">
                                    <input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}>

                                    <label class="form-check-label" for="remember">
                                        {{ __('Remember Me') }}
                                    </label>
                                </div>
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-8 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Login') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
resources/views/home.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">Dashboard</div>

                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif

                    You are logged in!
                    @auth('front')
                        Front
                    @endauth
                    @auth('back')
                        Back
                    @endauth
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

確認

http://localhost/login にフロントエンド用のユーザーで、
http://127.0.0.1/login にバックエンド用のユーザーでログインでき、
逆にしてエラーになればOK。

8
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?