この記事で共有した内容は、Laravel 5.1 フレームワークにおける ACL ユーザー認証および権限チェック機能の実装に関するものであり、一定の参考価値があり、困っている友人に役立つことを願っています。
1. はじめに
Laravel が提供するすぐに使える認証機能により、ユーザーの登録、ログイン、ログアウト、パスワードのリセットが便利かつ簡単になります。
しかし、サイトの特定の部分へのアクセスを制御する必要がある場合、または管理者以外のユーザーが特定のページを開いたり閉じたりできるようにする必要がある場合、または特定のユーザーが自分が公開するもの (記事など) のみを編集できるようにする必要がある場合は、以下を導入する必要があります。 BeatSwitch Lock ツールのようなもの、またはそのような関数を自分で手動で作成します。このような機能を ACL: アクセス制御リストと呼びます。これは、ユーザー レコードの属性に基づいて特定のものを操作または表示するためのユーザーの権限を定義するために使用されます。
幸いなことに、Laravel 5.1.11 以降、Laravel は上記の要件を達成するためのすぐに使える認証機能を提供するようになりました。追加の作業を行う必要はなくなり、それを使用するだけです。
注: このセクションを開始する前に、アップグレードガイドを参照して Laravel を Laravel 5.1.11 にアップグレードしてください。そうしないと、関連する機能が実装されません。
2.何ができるでしょうか?
Laravel が提供するすぐに使える ACL は Gate と呼ばれます (これは Spark のような製品名ではなく、単にクラスとファサードの名前です)。
Gate クラスを使用すると (インジェクションまたは Gate ファサードを使用)、特定のユーザー (現在ログインしているユーザーまたは指定されたユーザー) に特定の操作が許可されているかどうかを簡単に確認できます。チェック コードは次のとおりです。
if (Gate::denies('update-post', $post)) { abort(403); }
このコードをコントローラーに入れると、定義されたルール update-post を使用して、現在の認証済みユーザーに指定された記事を更新する権限があるかどうかがチェックされます。
拒否メソッドの逆である Gate::allows も使用できます。また、ブレード ビュー テンプレートの @can を通じて使用することもできます。他にもたくさんあります。次に見てみましょう。
3. 使い方は?
Laravel ACL は「権限」の概念に基づいて構築されており、権限には、true または false を返すキー (update-post など) とクロージャ (パラメータを渡すことができます) が含まれます。
3.1 権限の定義
AuthServiceProvider でユーザー更新ポスト権限 update-post を次のように定義しましょう:
<?php namespace App\Providers; use Illuminate\Contracts\Auth\Access\Gate as GateContract; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; class AuthServiceProvider extends ServiceProvider{ /** * 注册应用所有的认证/授权服务. * * @param \Illuminate\Contracts\Auth\Access\Gate $gate * @return void */ public function boot(GateContract $gate) { parent::registerPolicies($gate); $gate->define('update-post', function ($user, $post) { return $user->id === $post->user_id; }); } }
ご覧のとおり、現在のユーザーの場合、権限クロージャーを定義する最初のパラメーターは指定されたユーザーです。ログイン認証が通過しない場合、Gate は自動的に false を返します。
もちろん、クロージャに加えて、コンテナ内で解析される 2 番目のパラメータとしてクロージャをクラス メソッドに置き換えることもできます:
$gate->define('update-post', 'PostPolicy @update ');
3.2 ゲート ファサードを介した権限の確認
ゲートには、権限を確認するための次のメソッドが用意されています: チェック、許可、拒否 チェック機能と許可機能はまったく同じですが、拒否機能と許可機能は逆です。 。
ファサードを使用して権限を確認する場合、ユーザー インスタンスを渡す必要はありません。ゲート ファサードは自動的に現在のユーザーを渡します:
if (Gate::denies('update-post', $post)) { abort(403); }
権限で複数のパラメータを定義する場合:
Gate::define('delete-comment', function ($user, $post, $comment) { // });
チェック メソッド
if (Gate::allows('delete-comment', [$post, $comment])) { // }
現在認証されていないユーザーに操作権限があるかどうかを確認したい場合の呼び出し方法は次のとおりです:
if (Gate::forUser($user)->allows('update-post', $post)) { // }
3.3 ゲート インジェクションを使用して権限を確認します
いつものように、次のことができます。ファサードを使用する代わりに Gate クラスを注入します。 注入されたクラスはあなたのものと同じです。 AuthServiceProvider と同じです - IlluminateContractsAuthAccessGate:
public function somethingResolvedFromContainer(Gate $gate) { if ($gate->denies('update-post')) { // etc. } }
3.4 User モデルを使用して権限を確認します
Laravel の AppUser モデルは Authorizabletrait を使用するようになりました。それが提供する can メソッドとCannot メソッド。これらはそれぞれ、Gate の allowed メソッドと Denie メソッドに対応します。
そのため、User モデルを使用して権限を確認することもできます:
public function update(Request $request, $id) { $post = Post::findOrFail($id); if ($request->user()->cannot('update-post', $post)) { abort(403); } // 更新文章... }
3.5 Blade で権限を確認する
Blade で @can ディレクティブを使用して権限を確認できます:
<a href="/post/{{ $post->id }}">查看文章</a> @can('update-post', $post) <a href="/post/{{ $post->id }}/edit">编辑文章</a> @endcan
その反対は @else ディレクティブです。
@can('update-post', $post) <!-- The Current User Can Update The Post --> @else <!-- The Current User Can't Update The Post --> @endcan
3.6 権限チェックの中止
管理者またはスーパーユーザーがすべての権限を持っている場合はどうすればよいですか?あるいは、ユーザーの ACL ロジックを一時的に切り替えたい場合はどうすればよいでしょうか?
Gate が提供する before メソッドを使用すると、特定の状況下で権限をさらにチェックすることなく、他のチェックを実行する前に戻ることができます:
$gate->before(function ($user, $ability) { if ($user->last_name === 'Stauffer') { return true; } });
または、ユーザー独自のクラスを使用する場合:
$gate->before(function ($user, $ability) { if ($user->isOwner()) { return true; } });
3.7 Strategy クラス
アプリケーション ロジックの状況に応じて適切ますます複雑になり、処理する必要のあるアクセス許可がますます増えているため、すべてのアクセス許可を AuthServiceProvider で定義するのは明らかに賢明な考えではありません。そのため、Laravel では、いくつかのネイティブ PHP クラスであるストラテジー クラスが導入され、コントローラーは同様のものに基づいています。リソース グループのルーティング方法、ポリシー クラス グループのリソースに基づくアクセス許可の管理。
ポリシー クラスを生成する
次の Artisan コマンドを使用して PostPolicy ポリシー クラスを生成できます:
php artisan make:policy PostPolicy
生成されたポリシー クラスは app/Policies ディレクトリにあります。
その後、AuthServiceProvider のポリシー属性にポリシー クラスを登録できます:
protected $policies = [ Post::class => PostPolicy::class, ];
以下では、PostPolicy を次のように編集します:
<?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; } }
注: すべてのポリシー クラスはサービス コンテナを通じて解決されます。つまり、サービス コンテナで解決できます。ポリシー クラスのコンストラクター Type は依存関係を示唆しており、依存関係は自動的に挿入されます。
戦略をチェック
如果为某个资源类型定义了策略类,Gate将会使用第一个参数来判断检查策略类上的哪个方法。
因此,要检查是否有权限更新某篇文章,只需要传入文章实例和update权限:
<?php namespace App\Http\Controllers; use Gate; use App\User; use App\Post; use App\Http\Controllers\Controller; class PostController extends Controller{ /** * 更新给定文章 * * @param int $id * @return Response */ public function update($id) { $post = Post::findOrFail($id); if (Gate::denies('update', $post)) { abort(403); } // 更新文章... } }
当然也可以使用User模型和Blade指令检查权限。
此外,Laravel还提供了一个全局帮助函数policy来检查权限:
if (policy($post)->update($user, $post)) { // }
3.8 控制器授权
由于大多数授权都会在检查权限失败的情况下退出控制器方法,因此在控制器中检查权限有一条捷径(AuthorizesRequeststrait提供,该trait在基类控制器Controller中被使用):
<?php namespace App\Http\Controllers; use App\Post; use App\Http\Controllers\Controller; class PostController extends Controller{ /** * 更新给定文章 * * @param int $id * @return Response */ public function update($id) { $post = Post::findOrFail($id); $this->authorize('update', $post); // 更新文章... } }
和我们上面的例子一样,如果授权失败会抛出403错误。
最后,如果你的控制器方法名和策略类中的方法名相同,例如都是update,则可以省略authorize的第一个参数:
public function update($id){ $post = Post::findOrFail($id); $this->authorize($post); // 更新文章... }
此外,AuthorizesRequests也提供了对非当前认证用户权限检查的支持:
$this->authorizeForUser($user, 'update', $post);
相关文章推荐:
Laravel 5.1框架中如何创建自定义Artisan控制台命令
相关课程推荐:
以上がLaravel 5.1フレームワークでのACLユーザー認可および権限チェック機能の実装の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。