2017-07-25 12 views
4

Laravel 5.4プロジェクト(管理者用と正規ユーザー向けの1つ)に複数の認証ガードを実装しました。これまでのところうまくいき、管理者とユーザーの両方がログインできるようになりました。私は、両方の認証ガードの両方で動作するPolicyクラスを実装しようとしています。これは、すべての管理者に編集を許可し、モデルを所有するユーザーだけが編集できるようにする特定のモデルがあるためです。だから私はこの方法でポリシーを定義しました。1つのポリシーに対して複数の認証ガードを使用する

のApp \ポリシー\ ModelPolicyその後、私は私のモデルのために持っているものは何でもコントローラ方法で

public function update(User $user, Model $model) 
{ 
    if ($user->id === $model->user_id) { 
     return true; 
    } 

    if (Auth::guard('admin')->check()) { 
     return true; 
    } 

    return false; 
} 

のApp \のHttpコントローラは\ \ ModelController

public function update(Model $model) 
{ 
    $this->authorize('update', $model); 

    // update model 
} 

これを通常のユーザーがログインしている場合は完全に機能します。ただし、管理ユーザーがログインしている場合、それはポリシーにも達しません(私はエラーログからこれを知っています)。 Auth::check()のデフォルトのガードが失敗した場合、Policyクラスがリクエストを自動的に拒否する何かを実行していると推測しています。しかし、私のユーザーが(デフォルト以外の)いくつかのガードの1つを持つことは有効なので、私はこの動作を回避する必要があります。

私は私のコントローラメソッドで管理ロジックを実装し、唯一の私は非管理者を扱っています知っていれば、ポリシーを使用することができます知っている:

public function update(Model $model) 
{ 
    if (!Auth::guard('admin')->check()) { 
     $this->authorize('update', $model); 
    } 

    // update model 
} 

しかし、これはすぐにあれば制御不能にスパイラルすることができます私の管理者の状態は、単にログインしているよりも複雑です。もっと重要なのは、この論理のすべてがポリシーに属していて、私のコントローラーを泥沼にしているわけではありません。

複数の認証ガードに対してどのように同じポリシークラスを使用できますか?

+0

私はまったく同じ状況にあります。 – llioor

答えて

0

私は正しいガードデフォルトのガード作るためにベースコントローラクラスのauthorizeメソッドをオーバーライドすることになりました。次に、私のポリシーに渡された引数$userは、現在のユーザがログインしているAuthガードのインスタンスになります。

アプリ/ HTTP /コントローラ/ Controller.php

use Auth 

class Controller extends BaseController 
{ 
    use DispatchesJobs, ValidatesRequests; 
    use AuthorizesRequests { 
     authorize as protected baseAuthorize; 
    } 

    public function authorize($ability, $arguments = []) 
    { 
     if (Auth::guard('admin')->check()) { 
      Auth::shouldUse('admin'); 
     } 

     $this->baseAuthorize($ability, $arguments); 
    } 
} 

今ポリシー私のUserモデルや私の管理モデルのいずれかに渡されます、私は削除していることを確認する必要があること引数の型ヒントと渡されるモデルの型をチェックします。Auth::check()は、渡される$userが必要な型のログインユーザーでなければならないことを知っているので、何もする必要はありません。

のApp \方針はModelPolicy

use App\User; 

public function update($user, Model $model) 
{ 
    if ($user instanceof User) { 
     return $user->id == $userId; 
    } 

    // Is an Admin 
    return true; 
} 

\そして今、私は私が私のポリシーでそれをやりたいために必要な認証ガードへのアクセス権を持っています。

0

あなたの共通のコントローラ(/app/Http/Controllers/Controller.php)で「承認する」メソッドをオーバーライドすることができます

class Controller extends BaseController 
{ 
    use AuthorizesResources, DispatchesJobs, ValidatesRequests; 
    use AuthorizesRequests { 
     authorize as protected laravelAuthorize; 
    } 

    public function authorize($ability, $arguments = []) 
    { 
     if (!Auth::guard('admin')->check()) { 
      $this->laravelAuthorize($ability, $arguments); 
     } 
    } 
} 
+0

これは、オーバーライドされたメソッドにロジックを追加することで少しコントローラコードを簡略化します。問題は、これは、この状態をハードコードすることです。管理者ユーザーに関連する各コントローラメソッドに複数の条件があります(私の例では単純化したバージョンを使用しました)。カスタムロジックが各メソッドで機能するという私のポリシーに達することができれば、問題はLaravelが私がポリシーに達するのを止めることです。ポリシークラスのカスタマイズとシンプルさを私に提供するソリューションが本当に大好きです。 –

+0

あなたのソリューションは私が探していたものではありませんでしたが、それは 'authorize'メソッドをオーバーライドする正しい方向で私を指摘しました。ありがとう! –

関連する問題