ホームページ >バックエンド開発 >PHPチュートリアル >[ Laravel 5.2 ドキュメント ] サービス -- ユーザー認証

[ Laravel 5.2 ドキュメント ] サービス -- ユーザー認証

WBOY
WBOYオリジナル
2016-06-23 13:18:38930ブラウズ

1. はじめに

Laravel は、すぐに使える認証サービスを提供するだけでなく、リソースへのアクセスを制御するための承認ロジックを管理する簡単な方法も提供します。 Laravel には、認可ロジックの管理に役立つさまざまなメソッドとヘルパー関数があり、このドキュメントではこれらのメソッドを 1 つずつ説明します。

2. 権限 (能力) を定義する

ユーザーが特定のアクションを実行する権限を持っているかどうかを判断する最も簡単な方法は、IlluminateAuthAccessGate クラスを使用して「権限」を定義することです。 AuthServiceProvider ですべての権限を定義します。たとえば、現在の User モデルと Post モデルを受け取る update-post 権限を定義します。この権限では、ユーザー ID が記事の user_id と一致するかどうかを判断します。 not check $user が NULL かどうかにかかわらず、ユーザーがログインしていないか、ユーザーが forUser メソッドで指定されていない場合、Gate はすべての権限に対して自動的に false を返します。

クラスベースのパーミッション

認可コールバッククロージャの登録に加えて、必要に応じてパーミッションクラス名とクラスメソッドを渡すことでパーミッションメソッドを登録することもできます:

<?phpnamespace 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;        });    }}

クラスはサービスコンテナを通じて解析されます。

認証チェックのインターセプト

場合によっては、指定したユーザーにすべてのアクセス許可を付与する必要がある場合があります。このシナリオでは、 before メソッドを使用して、他のすべての承認チェックの前に実行されるコールバックを定義する必要があります:

$gate->define('update-post', 'PostPolicy@update');

if before。コールバックが null 以外の結果を返した場合、その結果はチェックの結果として使用されます。

after メソッドを使用して、他のすべての承認チェックの後に実行されるコールバックを定義することもできます。違いは、after コールバックでは承認チェックの結果を編集できないことです。

ゲートファサードを通過

権限を定義した後、さまざまな方法で権限を「確認」できます。まず、ゲート ファサードのチェック、許可、または拒否メソッドを使用できます。これらのメソッドはすべて、パーミッション名とパーミッション コールバックに渡される引数をパラメータとして受け取ります。 Gate はコールバックに渡された引数に現在のユーザーを自動的に追加するため、これらのメソッドに現在のユーザーを渡す必要はありません。そのため、前に定義した update-post 権限をチェックするときは、Post インスタンスを渡すだけで済みます。 denies メソッド:

$gate->before(function ($user, $ability) {    if ($user->isSuperAdmin()) {        return true;    }});

もちろん、allows メソッドとdenies メソッドは相対的なものであり、アクションが承認されている場合、check メソッドは allowed メソッドのエイリアスです。

指定したユーザーの権限を確認します

Gate ファサードを使用して、現在のユーザー以外に権限があるかどうかを判断したい場合は、forUser メソッドを使用できます:

$gate->after(function ($user, $ability, $result, $arguments) {    //});

複数のパラメーターを渡します

もちろん、パーミッションのコールバックは複数のパラメータを受け取ることもできます:

<?phpnamespace 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', $post)) {            abort(403);        }        // 更新文章...    }}

パーミッションに複数のパラメータが必要な場合は、パラメータ配列を Gate メソッドに渡すだけです:

if (Gate::forUser($user)->allows('update-post', $post)) {    //}

User モデルを通じて

User を通じてパーミッションを確認することもできます。モデルインスタンス。デフォルトでは、Laravel の AppUser モデルは Authorizabletrait を使用して、can とCannot の 2 つのメソッドを提供します。これら 2 つのメソッドの機能は、ゲート ファサードの許可メソッドと拒否メソッドに似ています。したがって、前の例を使用すると、コードは次のように変更できます:

Gate::define('delete-comment', function ($user, $post, $comment) {    //});

もちろん、can メソッドは Can メソッドの逆です:
if (Gate::allows('delete-comment', [$post, $comment])) {    //}

Blade

テンプレート エンジンをチェックインします

便宜上、 Laravel は、現在のユーザーが指定された権限を持っているかどうかをすばやく確認するための Blade ディレクティブ @can を提供します。例:
<?phpnamespace App\Http\Controllers;use App\Post;use Illuminate\Http\Request;use App\Http\Controllers\Controller;class PostController extends Controller{    /**     * 更新给定文章     *     * @param  \Illuminate\Http\Request  $request     * @param  int  $id     * @return Response     */    public function update(Request $request, $id)    {        $post = Post::findOrFail($id);        if ($request->user()->cannot('update-post', $post)) {            abort(403);        }        // 更新文章...    }}
@can ディレクティブと @else ディレクティブを一緒に使用することもできます:
if ($request->user()->can('update-post', $post)) {    // 更新文章...}

フォームリクエストをチェックインする

の authorize メソッドでゲート定義のアクセス許可を使用することも選択できます。フォームリクエスト。例:

<a href="/post/{{ $post->id }}">View Post</a>@can('update-post', $post)    <a href="/post/{{ $post->id }}/edit">Edit Post</a>@endcan

4. ポリシー

ポリシークラスを作成する

AuthServiceProvider ですべての認可ロジックを定義すると、特に大規模なアプリケーションではますます肥大化し、煩雑になるため、Laravel では認可ロジックを分割できます。 Strategy クラスは、認可リソースに基づいて認可ロジックをグループ化するネイティブ PHP クラスです。

まず、Post モデルの認可を管理するポリシー クラスを生成しましょう。アーティザン コマンド make:policy を使用してポリシー クラスを生成できます。生成されたポリシー クラスは、app/Policies ディレクトリにあります。
@can('update-post', $post)    <!-- The Current User Can Update The Post -->@else    <!-- The Current User Can't Update The Post -->@endcan

ポリシー クラスを登録する

ポリシー クラスが生成されたら、それを Gate クラスに登録する必要があります。 AuthServiceProvider には、エンティティとエンティティを管理するポリシー クラスをマップするためのポリシー属性が含まれています。したがって、Post モデルのポリシー クラスが PostPolicy であることを指定します。

/** * 判断请求用户是否经过授权 * * @return bool */public function authorize(){    $postId = $this->route('post');    return Gate::allows('update', Post::findOrFail($postId));}

ポリシー クラスの作成

ポリシー クラスが生成され登録された後、承認されたアクセス許可ごとにメソッドを追加できます。たとえば、PostPolicy で更新メソッドを定義し、特定のユーザーが投稿を更新できるかどうかを決定します。

<?phpnamespace 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;    }}

你可以继续在策略类中为授权的权限定义更多需要的方法,例如,你可以定义 show,  destroy, 或者  addComment方法来认证多个 Post动作。

注意:所有策略类都通过服务容器进行解析,这意味着你可以在策略类的构造函数中类型提示任何依赖,它们将会自动被注入。

拦截所有检查

有时候,你可能希望对指定用户授予所有权限,在这种场景中,需要使用 before方法定义一个在所有其他授权检查之前运行的回调:

$gate->before(function ($user, $ability) {    if ($user->isSuperAdmin()) {        return true;    }});

如果 before回调返回一个非空结果,那么该结果则会被当做检查的结果。

检查策略

策略类方法的调用方式和基于授权回调的闭包一样,你可以使用 Gate门面, User模型, @can指令或者辅助函数 policy。

通过 Gate 门面

Gate将会自动通过检测传递过来的类参数来判断使用哪一个策略类,因此,如果传递一个 Post实例给 denies方法,相应的, Gate会使用 PostPolicy来进行动作授权:

<?phpnamespace 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 模型

User模型的 ffbe95d20f3893062224282accb13e8fcan1cd55414ff5abdfea5dd958e7e547fdd 和 ffbe95d20f3893062224282accb13e8fcannot1cd55414ff5abdfea5dd958e7e547fdd 方法将会自动使用给定参数中有效的策略类。这些方法提供了便利的方式来为应用接收到的任意 ffbe95d20f3893062224282accb13e8fUser1cd55414ff5abdfea5dd958e7e547fdd 实例进行授权:

if ($user->can('update', $post)) {    //}if ($user->cannot('update', $post)) {    //}

在 Blade 模板中使用

类似的,Blade 指令 @can将会使用参数中有效的策略类:

@can('update', $post)    <!-- The Current User Can Update The Post -->@endcan

通过辅助函数 policy

全局的辅助函数 policy用于为给定类实例接收策略类。例如,我们可以传递一个 Post实例给帮助函数 policy来获取相应的 PostPolicy类的实例:

if (policy($post)->update($user, $post)) {    //}

5、 控制器授权

默认情况下,Laravel 自带的控制器基类 App\Http\Controllers\Controller使用了 AuthorizesRequeststrait,该 trait 提供了可用于快速授权给定动作的 authorize方法,如果授权不通过,则抛出 HttpException异常。

该 authorize方法和其他多种授权方法使用方法一致,例如 Gate::allows和 $user->can()。因此,我们可以这样使用 authorize方法快速授权更新 Post的请求:

<?phpnamespace 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);        // 更新文章...    }}

如果授权成功,控制器继续正常执行;然而,如果 authorize方法判断该动作授权失败,将会抛出 HttpException异常并生成带 403 Not Authorized状态码的HTTP响应。正如你所看到的, authorize方法是一个授权动作、抛出异常的便捷方法。

AuthorizesRequeststrait还提供了 authorizeForUser方法用于授权非当前用户:

$this->authorizeForUser($user, 'update', $post);

自动判断策略类方法

通常,一个策略类方法对应一个控制器上的方法,例如,在上面的 update方法中,控制器方法和策略类方法共享同一个方法名: update。

正是因为这个原因,Laravel 允许你简单传递实例参数到 authorize方法,被授权的权限将会自动基于调用的方法名进行判断。在本例中,由于 authorize在控制器的 update方法中被调用,那么对应的, PostPolicy上 update方法将会被调用:

/** * 更新给定文章 * * @param  int  $id * @return Response */public function update($id){    $post = Post::findOrFail($id);    $this->authorize($post);    // 更新文章...}
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。