3
3

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 3 years have passed since last update.

Laravel6.7でマルチログインをできる限り自分好みに実装したはなし

Posted at

システムユーザを、利用者と管理者で分けたいと思ったので、Laravelの認証の仕組みでそれを実現しないといけなくなりました。
期待通りの動作はしていますが、なんとなく不安なのと、また次あったら嫌なので、覚書きしておくことにしました。

認証機能使う上で実現したかったこと

  • テーブルの項目を好きにしたかった
  • テーブル1個で実現したかった

概ね実現できました。

分からなかったこと

  1. user,adminとテーブル分けなくても良いか
  • どうやって利用者や管理者として認証するのか
  • 認証の契機は何か
  • ディレクトリ構造とかってなんでもいいのか

大体理解できました。

やってないこと

  • パスワードリセット

ここからは、どのように実現したのかを書いていきます。

サービスプロバイダとドライバの設定(謎

confg/auth.php

// おそらく38行目付近

    'guards' => [
        'users' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'token',
            'provider' => 'users',
            'hash' => false,
        ],
        'admins' => [
            'driver' => 'session',
            'provider' => 'admins',
        ],
    ],

driverとproviderをまず設定するんだけど、driverはログインした後のセッションに関連しているのではないかと思われる。
adminsでログインしたらlogin_adminsみたいなセッションの名前に利用されたりするのではないか。
driverはsession以外選択するとどうなるんだろう。

image.png

providerはserviceプロバイダと連携ができるのかなって思ってるけど、良く知らない。
分かってるのは、app/providerに定義したファイルが無くても落ちないこと。

Modelとの関連付け

今度はModelとの関連付け。
EloquentはDB使うときの何かみたいな感じ。
言葉で説明しなくても、みんないつも使ってるだろ?

confg/auth.php

// おそらく75行目付近

        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],
        'admins' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],

テーブル同じやつ使いたいっていうなら、ここのmodelをこのようにしておけば良い。

Modelの調整

今度は、User.phpを、自分のDBと同じように調整していく。
とりあえず、最初からあるやつは触らないようにしておいた。

app/Http/User.php

    use Notifiable;
    protected $table = 'm_auth';  // ここに自分のDBのテーブルの名前
    protected $primaryKey = 'u_id'; // ここに自分のDBのテーブルのプリキーの名前


    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'l_id', 'password', 'l_login', 'join_date'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];


テーブル名とかキー名とかはこの記事用にテキトーです。fillableは、レコード取得した時に取得したい項目で、hiddenは要らない項目。
tableとprimaryKeyは自分とこのと同じにできる。ただ、このremenber_tokenだけは何ともならんと思うので、
既存の改修をする場合は、項目追加する必要があるかもしれない。無いかもしれないけどね。わしゃ分からんかった。

準備完了。でこれ、どんな契機で使うの?

ここまでやって、自分はこのタイトルのように思いました。
Laravelの最初からあるコード見ると、全部traitん中に書いてあるけど、
postしたデータがtraitん中で勝手に処理されてるようにしか見えない。

悩むのも面倒なので、テストにそれっぽいやつエイヤーする。

したいのはやまやまですが、これをやる前には、テストデータが一つ必要になります。
Laravelの認証使うなら、パスワードはHash::Makeしたものでないとダメです。
一緒に作りましょう。

test/Unit/ExampleTest.php


public function testDataTukuruzeeeeee()
    {

        $user = new User();
        $user->******_id = 'hogeyama';
        $user->password = Hash::make('123456');
        $user->***_**** = '2019/12/20 11:38';
        $user->****_**_*** = '2019/12/20 11:38';

        $user->save();

        $user = new User();
        $res = $user->where(['******_id' => 'hogeyama'])->first();
        debug($res);

        $this->assertTrue(true);
    }


テストデータができたら、ログインしてみましょう。

test/Unit/ExampleTest.php


public function testLoginSuruzeeeee()
    {

        $auth = \Auth::attempt([
            '******_id' => 'hogeyama',
            'password' => '123456'
        ],true);  // true大事


        $user = new User();
        $res = $user->where(['******_id' => 'hogeyama'])->first();
        debug($res);
        
        $this->assertTrue(true);
    }


remember_tokenの中に値入っていれば大丈夫だと思われます。
というわけで、Auth::attemptでログインすると良いと思います。
他にも方法はあります。

Laravel 5.7 認証

ちなみに、ここでAuth::attemptをtrueしないと、後のページで認証後のデータ使えないので、
remenber_token項目とtrue必須です。

あれ、認証は?利用者とか管理者とかは?

Auth::Guard('admins')とやると良いみたいですよ!

test/Unit/ExampleTest.php


public function testLoginSuruzeeeee()
    {

        $auth = \Auth::Guard('admins')->attempt([
            '******_id' => 'hogeyama',
            'password' => '123456'
        ],true);


        $user = new User();
        $res = $user->where(['******_id' => 'hogeyama'])->first();
        debug($res);
        
        $this->assertTrue(true);
    }

Auth使うと良いなと思ったこと

  • ログイン状態の確認が楽
  • 直接ページのURLを叩くすけべぇな輩への手軽な対策ができる

ログイン状態の確認が楽

constractでmiddlewareで最初にログイン確認できます。


   public function __construct()
    {
        $this->middleware('auth')
    }

middlewareの中に入る文字は、kernelで確認できます。

app/Http/Kernel.php

    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    ];


web.phpで使うと、RouteGroup飛んで来たやつに対して対策できます。


Route::group(['middleware' => ['guest']], function() {

    Route::get('/abeshi', 'hidebuController@get_hidebu')->name('abesi');

}

とすることで、abesiにこようとすると、

\App\Http\Middleware\RedirectIfAuthenticated::class

こいつが先に動くので、この中でごにょごにょやると快適なスケベ対策になると思います。

おわり

ハマった割に、そんな書くことないなと思ってたんですが、書いてみると多いもんですね。
なるべくわかりやすくと思ったんですが、ややこしい感じになっちゃうんですね~。

3
3
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
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?