ユーザー認証
- はじめに
- ゲート
- ポリシーの生成
- ポリシーの登録
- #ストラテジの記述
ストラテジ メソッド - モデル メソッドは含まれません
- ゲスト - ユーザー
- ポリシー フィルター
- ポリシーの認証解除アクションを使用
ユーザー モデル経由 - #ミドルウェア経由
#ゲート
Gates の記述
Gates は、ユーザーが特定のアクションを実行する権限を持っているかどうかを判断するために使用されるクロージャ関数であり、一般的な方法は、App\Providers\AuthServiceProvider でそれを使用することです。
Gate
を定義します。Gates は常に最初のパラメーターとしてユーザー インスタンスを受け取り、関連する Eloquent モデルなどのオプションのパラメーターを受け取ることができます:
/** * 注册任意用户认证、用户授权服务。 * * @return void */ public function boot(){ $this->registerPolicies(); Gate::define('update-post', function ($user, $post) { return $user->id == $post->user_id; }); }
Gates は同様のコントローラーも使用できますメソッド Class@method
定義するスタイル コールバック文字列:
/** * 注册任意用户认证、用户授权服务。 * * @return void */ public function boot(){ $this->registerPolicies(); Gate::define('update-post', 'App\Policies\PostPolicy@update'); }
ResourceGates
resource
メソッドを使用して定義することもできます複数のゲート メソッドを同時に実行:
Gate::resource('posts', 'App\Policies\PostPolicy');
上記の手動定義は、次のゲート定義と同じ効果があります:
Gate::define('posts.view', 'App\Policies\PostPolicy@view'); Gate::define('posts.create', 'App\Policies\PostPolicy@create'); Gate::define('posts.update', 'App\Policies\PostPolicy@update'); Gate::define('posts.delete', 'App\Policies\PostPolicy@delete');
デフォルトでは、view# は ##, ## として定義されます#create
、update
、および delete
メソッド。 3 番目のパラメータとして配列を resource
メソッドに渡します。デフォルトのメソッドをオーバーライドしたり、デフォルトのメソッドに追加したりできます。配列のキーは機能の名前を定義し、値はメソッドの名前を定義します。たとえば、次のコードは 2 つの新しいゲート定義 (posts.image
と posts.photo
:Gate::resource('posts', 'PostPolicy', [
'image' => 'updateImage',
'photo' => 'updatePhoto',
]);
allows
またはdenies メソッドを使用する必要があります。現在の認証済みユーザーをこれらのメソッドに渡す必要はないことに注意してください。 Laravel は認証されたユーザーを自動的に処理し、それを gete クロージャー関数に渡します。
if (Gate::allows('update-post', $post)) { // 指定当前用户可以进行更新... } if (Gate::denies('update-post', $post)) { // 指定当前用户不能更新... }
特定のユーザーがアクションへのアクセスを許可されているかどうかを確認したい場合は、
Gate## を使用できます。ファサードの #forUser メソッド:if (Gate::forUser($user)->allows('update-post', $post)) {
// 用户可以更新...
}
if (Gate::forUser($user)->denies('update-post', $post)) {
// 用户不能更新...
}
メソッドを使用して、他のすべての承認チェックの前に実行されるコールバックを定義できます。
Gate::before(function ($user, $ability) { if ($user->isSuperAdmin()) { return true; } });
before
コールバック メソッドが null 以外の結果を返した場合、その結果が検査結果として考慮されます。
after
メソッドを使用して、各承認チェックの後に実行されるコールバックを定義できます。ただし、
コールバック メソッドから承認チェックの結果を変更することはできません。
は、Gate::after(function ($user, $ability, $result, $arguments) {
//
});
before
チェックと同様です。 ## コールバックが null 以外の結果を返した場合、その結果はチェック結果として扱われます。
ポリシーの生成
ポリシーは、特定のモデルまたはリソースの認可ロジックを編成するクラスです。たとえば、アプリケーションがブログの場合、ブログを作成または更新するときに、ユーザーのアクションを承認するための Post
モデルと対応する PostPolicy
が必要になることがあります。
artisan command
artisan command 職人コマンドの
make:policy 職人コマンド コマンドを使用して、ポリシーを生成できます。生成されたポリシーは、
app/Policies
php artisan make:policy PostPolicy
make:policy このコマンドは空のポリシー クラスを生成します。生成するクラスに基本的な「CRUD」戦略メソッドが含まれている場合は、コマンドの実行時に
--model オプションを指定できます: php artisan make:policy PostPolicy --model=Post{tip} すべての戦略は次のとおりです。 Laravel のサービス コンテナを通じて解析されるため、ポリシー コンストラクターで必要な依存関係をタイプヒントで指定し、それらを自動的に挿入できます。
#ポリシーの登録
ポリシーが存在したら、登録する必要があります。新しい Laravel アプリケーションに含まれる AuthServiceProvider
には、さまざまなモデルをポリシーにマップする policies
プロパティがあります。ポリシーを登録すると、指定されたモデルにアクセスするアクションを承認するときにどのポリシーを使用するかを Laravel に指示します:
<?php namespace App\Providers; use App\Post;use App\Policies\PostPolicy; use Illuminate\Support\Facades\Gate; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; class AuthServiceProvider extends ServiceProvider{ /** * 应用的策略映射。 * * @var array */ protected $policies = [ Post::class => PostPolicy::class, ]; /** * 注册任意应用认证、应用授权服务 * * @return void */ public function boot() { $this->registerPolicies(); // } }
ポリシー自動検出
モデルとポリシーが次のとおりである限り標準的な Laravel の命名 慣例により、Laravel はモデル戦略を手動で登録する代わりに、自動的に戦略を検出できます。具体的には、ポリシーは、モデルが含まれるディレクトリの下の Policies
ディレクトリに配置する必要があります。したがって、たとえば、モデルを app
ディレクトリに配置し、ポリシーを app/Policies
ディレクトリに配置できます。さらに、ポリシー名はモデル名と一致し、Policy
サフィックスが付いている必要があります。したがって、User
モデルは UserPolicy
クラスに対応します。
独自のポリシー検出ロジックを提供する場合は、Gate::guessPolicyNamesUsing
メソッドを使用してカスタム コールバックを登録できます。通常、このメソッドはアプリケーションの AuthServiceProvider
の boot
メソッドから呼び出す必要があります。
use Illuminate\Support\Facades\Gate; Gate::guessPolicyNamesUsing(function ($modelClass) { // return policy class name... });
ライティング戦略##{note}
AuthServiceProvider
で明示的マッピングされているポリシーは、自動検出ポリシーよりも優先されます。
戦略メソッド
認可ポリシーを登録すると、認可後の各アクションのメソッドを追加できます。たとえば、PostPolicy
で update
メソッドを定義します。このメソッドは、指定された User
が指定された Post
インスタンスを更新できるかどうかを決定します。
update
メソッドは、パラメータとして User
インスタンスと Post
インスタンスを受け取り、true
または false# を返す必要があります。 ## ユーザーが指定された
Post を更新する権限を持っているかどうかを示します。したがって、この例では、ユーザーの
id が投稿内の
user_id と一致するかどうかを判断する必要があります。
<?php namespace App\Policies;use App\User; use App\Post;class PostPolicy{ /** * 判断该方法能否被用户操作。 * * @param \App\User $user * @param \App\Post $post * @return bool */ public function update(User $user, Post $post) { return $user->id === $post->user_id; } }この認可ポリシーに対して追加のメソッドを引き続き定義できます。たとえば、
view または
delete メソッドを定義して
Post の複数の動作を承認したり、カスタム戦略メソッドに好きな名前を付けることもできます。 。
{ヒント} Artisan コンソールでストラテジーを生成するときに--model
オプションを使用すると、
view、
が含まれます。 create、
update、および
deleteアクション メソッド。
一部のポリシー メソッドは、現在認証されているユーザーのみをパラメーターとして受け取ります。認可関連のモデルインスタンスを渡す方法。最も一般的なアプリケーション シナリオは、
create アクションを承認することです。たとえば、ブログを作成している場合、まず現在のユーザーにブログを作成する権限があるかどうかを確認することができます。 モデル インスタンスを渡す必要のないストラテジ メソッド (
メソッドなど) を定義する場合、モデル インスタンスをパラメーターとして受け取りません。許可されたユーザーのみをパラメーターとして受け入れるようにこのメソッドを定義する必要があります。 /**
* 判断用户是否可以创建请求。
*
* @param \App\User $user
* @return bool
*/
public function create(User $user){
//
}
デフォルトでは、受信 HTTP リクエストが認証されたユーザーによって開始されたものでない場合、すべてのゲートと戦略は自動的に
false を返します。ただし、「オプション」タイプ ヒントを宣言するか、ユーザー パラメーター定義に null
デフォルト値を指定することで、これらの認可チェックをゲートやポリシーに渡すことができます:
# ##############################<?php
namespace App\Policies;
use App\User;use App\Post;class PostPolicy{
/**
* 判断用户是否能更新指定帖子。
*
* @param \App\User $user
* @param \App\Post $post
* @return bool
*/
public function update(?User $user, Post $post)
{
return $user->id === $post->user_id;
}
}
ポリシー フィルター
特定のユーザーに対して、指定したポリシーを通じてすべてのアクションを承認することができます。この目標を達成するには、ストラテジーで before
メソッドを定義します。 before
メソッドは、ポリシー内の他のすべてのメソッドの前に実行され、指定されたポリシー メソッド以外のアクションが判断を実行することを許可する方法を提供します。この機能の最も一般的なシナリオは、アプリケーションの管理者にすべてのアクションへのアクセスを許可することです。
public function before($user, $ability){ if ($user->isSuperAdmin()) { return true; } }
ユーザーに対するすべての許可を拒否したい場合は、before# で ## を返す必要があります。 ## メソッド #false
。戻り値が null
の場合、このポリシーでは承認は失敗します。
beforeポリシー承認アクションを使用する#ユーザーモデルを通じてLaravel の組み込みメソッドは呼び出されません。
User
モデルには、アクションを承認するための 2 つの便利なメソッドcan と
cant が含まれています。この
can メソッドでは、承認されたアクションと関連モデルを指定する必要があります。たとえば、ユーザーが指定された
Post モデルを更新する権限を持っているかどうかを判断するには:
if ($user->can('update', $post)) { // }
"指定されたモデルの
ポリシーが登録されている " の場合、 can このメソッドは、適切なストラテジを自動的に呼び出し、ブール値を返します。このモデルにストラテジーが登録されていない場合、can メソッドは、指定されたアクション名に一致するクロージャーベースのゲートの呼び出しを試みます。
create
などの一部のアクションでは、モデル インスタンスを指定する必要がないことに注意してください。この場合、クラス名をcan メソッドに渡します。このクラス名は、使用するポリシー認可アクションを決定するために使用されます:
use App\Post;if ($user->can('create', Post::class)) { // 执行相关策略中的 "create" 方法... }
Via middlewareLaravel には次のものが含まれますリクエストがルートまたはコントローラーに到達する前にアクションを承認できるミドルウェア。デフォルトでは、Illuminate\Auth\Middleware\Authorize
ミドルウェアは、App\Http\Kernel クラスの
can キーに割り当てられます。承認されたユーザーがブログを更新する例を使用して、
can ミドルウェアの使用方法を説明します。
use App\Post;Route::put('/post/{post}', function (Post $post) { // 当前用户可以进行更新操作... })->middleware('can:update,post');
この例では、
can ミドルウェア 2 を渡しました。パラメーター。最初のパラメータは承認が必要なアクションの名前で、2 番目のパラメータはポリシー メソッドに渡すルーティング パラメータです。この場合、「暗黙的なルート バインディング」を使用し、Post モデルが戦略メソッドに渡されます。ユーザーが指定されたアクションへのアクセスを許可されていない場合、このミドルウェアは
403 ステータス コードを含む HTTP 応答を生成します。
指定されたモデルを必要としないアクション
同様に、create
などの一部のアクションはモデル インスタンスを必要としない場合があります。この場合、クラス名をミドルウェアに渡すことができます。このアクションを承認するとき、このクラス名は、使用するポリシーを決定するために使用されます:
Route::post('/post', function () { // 当前用户可以进行创建操作... })->middleware('can:create,App\Post');
コントローラー ヘルパー関数を通じて
User
モデルでヘルパー メソッドを提供することに加えて、Laravel は、App\Http\Controllers\Controller
基本クラスを継承するコントローラー用の便利な も提供します。 authorize
メソッド。 can
メソッドと同様に、このメソッドは承認するアクションと関連モデルをパラメーターとして受け取る必要があります。このアクションが承認されていない場合、authorize
メソッドは Illuminate\Auth\Access\AuthorizationException
の例外をスローし、Laravel のデフォルトの例外ハンドラーはこの例外を # の例外に変換します。 ##403 HTTP 応答ステータス コード。
<?php namespace App\Http\Controllers; use App\Post;use Illuminate\Http\Request; use App\Http\Controllers\Controller; class PostController extends Controller{ /** * 更新指定博客帖子。 * * @param Request $request * @param Post $post * @return Response * @throws \Illuminate\Auth\Access\AuthorizationException */ public function update(Request $request, Post $post) { $this->authorize('update', $post); // 当前用户可以更新博客... } }モデルのアクションを指定する必要はありません前述したように、
create などの一部のアクションは指定する必要がありません。モデル インスタンスのアクション。この場合、クラス名を
authorize メソッドに渡すことができます。このアクションを承認する場合、このクラス名を使用して、どのポリシーを使用するかを決定します。
/** * 创建一个新的博客 * * @param Request $request * @return Response * @throws \Illuminate\Auth\Access\AuthorizationException */ public function create(Request $request){ $this->authorize('create', Post::class); // 当前用户可以新建博客... }認可リソース コントローラーリソース コントローラーを使用している場合は、コントローラー コンストラクターで
authorizeResource メソッドを使用できます。このメソッドは、適切な
can ミドルウェアをリソース コントローラーの対応するメソッドにアタッチします。
authorizeResource このメソッドは、テンプレート クラス名を最初のパラメーターとして受け取り、モデル ID を含むルート/リクエスト パラメーターの名前を 2 番目のパラメーターとして受け取ります。 # #{ヒント}
make:policy
--modelオプションとともに使用すると、指定されたモデルに基づいてポリシー クラスを迅速に生成できます。ポリシー PostPolicy --model=Post
。
ブレード テンプレートを使用するブレード テンプレートを作成するとき、ページの特定の部分だけを表示したい場合があります。指定されたアクションへのアクセスを許可されたユーザーに表示されます。たとえば、ブログを更新する権限を持つユーザーにのみ、更新されたフォームを表示したい場合があります。この場合、
@canなどの一連の命令を使用できます。
<?php namespace App\Http\Controllers; use App\Post;use Illuminate\Http\Request; use App\Http\Controllers\Controller; class PostController extends Controller{ public function __construct() { $this->authorizeResource(Post::class, 'post'); } }
これらの命令は @if
と書かれています。および @unless
ステートメントへのショートカット。
ステートメントと 他のほとんどの承認メソッドと同様、アクションにモデル インスタンスが必要ない場合は、クラス名を @cannot
ステートメントは、それぞれ次のステートメントに変換されます: @can('update', $post)
<!-- The Current User Can Update The Post -->
@elsecan('create', App\Post::class)
<!-- The Current User Can Create New Post -->
@endcan
@cannot('update', $post)
<!-- The Current User Can't Update The Post -->
@elsecannot('create', App\Post::class)
<!-- The Current User Can't Create New Post -->
@endcannot
モデルに依存しないアクション
@ can
および @ に渡すことができます。できません
手順: @if (Auth::user()->can('update', $post))
<!-- The Current User Can Update The Post -->
@endif
@unless (Auth::user()->can('update', $post))
<!-- The Current User Can't Update The Post -->
@endunless