Pintu dan strategi dalam Laravel

WBOY
Lepaskan: 2023-08-31 13:50:01
asal
1498 orang telah melayarinya

Pintu dan strategi dalam Laravel

Hari ini, kita akan membincangkan sistem kebenaran rangka kerja web Laravel. Rangka kerja Laravel melaksanakan kebenaran dalam bentuk gerbang dan dasar. Selepas memperkenalkan gerbang dan strategi, saya akan menunjukkan konsep dengan melaksanakan contoh tersuai.

Saya menganggap anda sudah tahu tentang sistem pengesahan Laravel terbina dalam, kerana ini diperlukan untuk memahami konsep kebenaran. Jelas sekali, sistem kebenaran berfungsi bersama-sama dengan sistem pengesahan untuk mengenal pasti sesi pengguna yang sah.

Jika anda tidak tahu tentang sistem pengesahan Laravel, saya sangat mengesyorkan anda membaca dokumentasi rasmi, ia akan memberi anda pemahaman yang mendalam tentang topik tersebut.

Kaedah kebenaran laravel

Buat masa ini, anda harus tahu bahawa sistem kebenaran Laravel datang dalam dua bentuk: gerbang dan polisi. Walaupun ini mungkin kedengaran seperti perkara yang rumit, saya akan mengatakan bahawa sebaik sahaja anda membiasakannya, ia agak mudah untuk dilakukan!

Gate membolehkan anda menentukan peraturan kebenaran menggunakan pendekatan berasaskan penutupan yang mudah. Dalam erti kata lain, apabila anda ingin membenarkan operasi yang tidak terikat dengan mana-mana model tertentu, gerbang adalah tempat yang sesuai untuk melaksanakan logik itu.

Mari kita lihat rupa kebenaran berasaskan pintu masuk:

...
...
Gate::define('update-post', function ($user, $post) {
  return $user->id == $post->user_id;
});
...
...
Salin selepas log masuk

Coretan kod di atas mentakrifkan peraturan kebenaran update-post yang boleh anda hubungi dari mana-mana sahaja dalam aplikasi anda. update-post 您可以从应用程序中的任何位置调用它。

另一方面,当您想要对任何模型的授权逻辑进行分组时,您应该使用策略。例如,假设您的应用程序中有一个 Post 模型,并且您想要授权该模型的 CRUD 操作。在这种情况下,这就是您需要实施的策略。

class PostPolicy
{
  public function view(User $user, Post $post) {}
  public function create(User $user) {}
  public function update(User $user, Post $post) {}
  public function delete(User $user, Post $post) {}
}
Salin selepas log masuk

如您所见,这是一个非常简单的策略类,定义了 Post 模型的 CRUD 操作的授权。

这就是 Laravel 中的门和策略的介绍。从下一节开始,我们将对每个元素进行实际演示。

大门

在本节中,我们将通过一个现实示例来理解门的概念。

如何创建自定义门

当您需要注册组件或服务时,您通常会寻找 Laravel 服务提供者。遵循该约定,让我们继续在 app/Providers/AuthServiceProvider.php 中定义自定义门,如以下代码片段所示。

<?php
namespace App\Providers;
 
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
 
class AuthServiceProvider extends ServiceProvider
{
  /**
   * The policy mappings for the application.
   *
   * @var array
   */
  protected $policies = [
    'App\Model' => 'App\Policies\ModelPolicy',
  ];
 
  /**
   * Register any authentication / authorization services.
   *
   * @return void
   */
  public function boot()
  {
    $this->registerPolicies();
     
    Gate::define('update-post', function ($user, $post) {
      return $user->id == $post->user_id;
    });
  }
}
Salin selepas log masuk

boot 方法中,我们定义了自定义门:

Gate::define('update-post', function ($user, $post) {
  return $user->id == $post->user_id;
});
Salin selepas log masuk

定义门时,它需要一个闭包,根据门定义中定义的授权逻辑,返回 TRUEFALSE 。除了闭包函数之外,还有其他方法可以定义门。

例如,以下门定义调用控制器操作而不是闭包函数。

Gate::define('update-post', 'ControllerName@MethodName');
Salin selepas log masuk

如何使用我们的自定义大门

现在,让我们继续添加自定义路由,以便我们可以演示基于门的授权如何工作。在路由文件 routes/web.php 中,添加以下路由。

Route::get('service/post/gate', 'PostController@gate');
Salin selepas log masuk

让我们也创建一个关联的控制器文件app/Http/Controllers/PostController.php

<?php
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use App\Post;
use Illuminate\Support\Facades\Gate;
 
class PostController extends Controller
{
  /* Make sure you don't use Gate and Policy altogether for the same Model/Resource */
  public function gate()
  {
    $post = Post::find(1);
 
    if (Gate::allows('update-post', $post)) {
      echo 'Allowed';
    } else {
      echo 'Not Allowed';
    }
     
    exit;
  }
}
Salin selepas log masuk

在大多数情况下,您最终会使用 allowsdenies 方法(Gate 外观)来授权特定操作。在上面的示例中,我们使用 allows 方法来检查当前用户是否能够执行 update-post 操作。

眼尖的用户会注意到我们只将第二个参数 $post 传递给了闭包。第一个参数是当前登录的用户,由 Gate 门面自动注入。

这就是您应该如何使用门来授权 Laravel 应用程序中的操作。如果您希望为模型实现授权,下一节将介绍如何使用策略。

政策

正如我们之前讨论的,当您想要对任何特定模型或资源的授权操作进行逻辑分组时,您需要的就是策略。

如何创建自定义策略

在本节中,我们将为 Post 模型创建一个策略,用于授权所有 CRUD 操作。我假设您已经在应用程序中实现了 Post 模型;否则,类似的事情也会做。

Laravel artisan 命令是创建存根代码时最好的朋友。您可以使用以下 artisan 命令为 Post 模型创建策略。

$php artisan make:policy PostPolicy --model=Post
Salin selepas log masuk

如您所见,我们提供了 --model=Post 参数,以便它创建所有 CRUD 方法。如果没有,它将创建一个空白策略类。您可以在 app/Policies/PostPolicy.php 中找到新创建的策略类。

<?php

namespace App\Policies;

use App\Post;
use App\User;
use Illuminate\Auth\Access\HandlesAuthorization;

class PostPolicy
{
    use HandlesAuthorization;

    /**
     * Determine whether the user can view any models.
     *
     * @param  \App\User  $user
     * @return mixed
     */
    public function viewAny(User $user)
    {
        //
    }

    /**
     * Determine whether the user can view the model.
     *
     * @param  \App\User  $user
     * @param  \App\Post  $post
     * @return mixed
     */
    public function view(User $user, Post $post)
    {
        //
    }

    /**
     * Determine whether the user can create models.
     *
     * @param  \App\User  $user
     * @return mixed
     */
    public function create(User $user)
    {
        //
    }

    /**
     * Determine whether the user can update the model.
     *
     * @param  \App\User  $user
     * @param  \App\Post  $post
     * @return mixed
     */
    public function update(User $user, Post $post)
    {
        //
    }

    /**
     * Determine whether the user can delete the model.
     *
     * @param  \App\User  $user
     * @param  \App\Post  $post
     * @return mixed
     */
    public function delete(User $user, Post $post)
    {
        //
    }

    /**
     * Determine whether the user can restore the model.
     *
     * @param  \App\User  $user
     * @param  \App\Post  $post
     * @return mixed
     */
    public function restore(User $user, Post $post)
    {
        //
    }

    /**
     * Determine whether the user can permanently delete the model.
     *
     * @param  \App\User  $user
     * @param  \App\Post  $post
     * @return mixed
     */
    public function forceDelete(User $user, Post $post)
    {
        //
    }
}
Salin selepas log masuk

让我们将其替换为以下代码。

<?php
namespace App\Policies;
 
use App\User;
use App\Post;
use Illuminate\Auth\Access\HandlesAuthorization;
 
class PostPolicy
{
  use HandlesAuthorization;
 
  /**
   * Determine whether the user can view the post.
   *
   * @param  \App\User  $user
   * @param  \App\Post  $post
   * @return mixed
   */
  public function view(User $user, Post $post)
  {
    return TRUE;
  }
 
  /**
   * Determine whether the user can create posts.
   *
   * @param  \App\User  $user
   * @return mixed
   */
  public function create(User $user)
  {
    return $user->id > 0;
  }
 
  /**
   * Determine whether the user can update the post.
   *
   * @param  \App\User  $user
   * @param  \App\Post  $post
   * @return mixed
   */
  public function update(User $user, Post $post)
  {
    return $user->id == $post->user_id;
  }
 
  /**
   * Determine whether the user can delete the post.
   *
   * @param  \App\User  $user
   * @param  \App\Post  $post
   * @return mixed
   */
  public function delete(User $user, Post $post)
  {
    return $user->id == $post->user_id;
  }
}
Salin selepas log masuk

为了能够使用我们的策略类,我们需要使用 Laravel 服务提供者注册它,如以下代码片段所示。

<?php
namespace App\Providers;
 
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use App\Post;
use App\Policies\PostPolicy;
 
class AuthServiceProvider extends ServiceProvider
{
  /**
   * The policy mappings for the application.
   *
   * @var array
   */
  protected $policies = [
    Post::class => PostPolicy::class
  ];
 
  /**
   * Register any authentication / authorization services.
   *
   * @return void
   */
  public function boot()
  {
    $this->registerPolicies();
  }
}
Salin selepas log masuk

我们已在 $policies

Sebaliknya, apabila anda ingin mengumpulkan logik kebenaran untuk mana-mana model, anda harus menggunakan strategi. Sebagai contoh, katakan anda mempunyai model Post dalam aplikasi anda dan anda ingin membenarkan operasi CRUD pada model tersebut. Dalam kes ini, ini adalah strategi yang perlu anda laksanakan. 🎜
Route::get('service/post/view', 'PostController@view');
Route::get('service/post/create', 'PostController@create');
Route::get('service/post/update', 'PostController@update');
Route::get('service/post/delete', 'PostController@delete');
Salin selepas log masuk
Salin selepas log masuk
🎜Seperti yang anda lihat, ini ialah kelas dasar yang sangat mudah yang mentakrifkan kebenaran untuk operasi CRUD bagi model Post. 🎜 🎜Itu sahaja, pengenalan kepada gerbang dan strategi dalam Laravel. Bermula di bahagian seterusnya, kami akan memberikan demonstrasi praktikal bagi setiap elemen. 🎜 🎜Pintu🎜 🎜Dalam bahagian ini, kita akan memahami konsep pintu melalui contoh kehidupan sebenar. 🎜

Cara membuat pintu tersuai

🎜Apabila anda perlu mendaftar komponen atau perkhidmatan, anda biasanya mencari penyedia perkhidmatan Laravel. Berikutan konvensyen itu, mari kita teruskan dan tentukan get tersuai dalam app/Providers/AuthServiceProvider.php seperti yang ditunjukkan dalam coretan kod berikut. 🎜
<?php
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use App\Post;
use Illuminate\Support\Facades\Auth;
 
class PostController extends Controller
{
  public function view()
  {
    // get current logged in user
    $user = Auth::user();
     
    // load post
    $post = Post::find(1);
     
    if ($user->can('view', $post)) {
      echo "Current logged in user is allowed to update the Post: {$post->id}";
    } else {
      echo 'Not Authorized.';
    }
  }
 
  public function create()
  {
    // get current logged in user
    $user = Auth::user();
 
    if ($user->can('create', Post::class)) {
      echo 'Current logged in user is allowed to create new posts.';
    } else {
      echo 'Not Authorized';
    }
 
    exit;
  }
 
  public function update()
  {
    // get current logged in user
    $user = Auth::user();
 
    // load post
    $post = Post::find(1);
 
    if ($user->can('update', $post)) {
      echo "Current logged in user is allowed to update the Post: {$post->id}";
    } else {
      echo 'Not Authorized.';
    }
  }
 
  public function delete()
  {
    // get current logged in user
    $user = Auth::user();
     
    // load post
    $post = Post::find(1);
     
    if ($user->can('delete', $post)) {
      echo "Current logged in user is allowed to delete the Post: {$post->id}";
    } else {
      echo 'Not Authorized.';
    }
  }
}
Salin selepas log masuk
Salin selepas log masuk
🎜Dalam kaedah boot, kami mentakrifkan pintu tersuai: 🎜
public function view()
{
  // get current logged in user
  $user = Auth::user();
   
  // load post
  $post = Post::find(1);
   
  if ($user->can('view', $post)) {
    echo "Current logged in user is allowed to update the Post: {$post->id}";
  } else {
    echo 'Not Authorized.';
  }
}
Salin selepas log masuk
Salin selepas log masuk
🎜Apabila mentakrifkan get, ia memerlukan penutupan yang mengembalikan TRUE atau FALSE bergantung pada logik kebenaran yang ditakrifkan dalam definisi get. Terdapat cara lain untuk menentukan gerbang selain fungsi penutupan. 🎜 🎜Sebagai contoh, definisi get berikut memanggil tindakan pengawal dan bukannya fungsi penutupan. 🎜
…
$this->authorize('view', $post);
…
Salin selepas log masuk
Salin selepas log masuk

Cara menggunakan pagar tersuai kami

🎜Sekarang, mari teruskan dan tambahkan laluan tersuai supaya kita boleh menunjukkan cara kebenaran berasaskan pintu berfungsi. Dalam fail laluan routes/web.php, tambahkan laluan berikut. 🎜
Route::put('/post/{post}', function (Post $post) {
    // Currently logged-in user is allowed to update this post.... 
})->middleware('can:update,post');
Salin selepas log masuk
Salin selepas log masuk
🎜Mari buat juga fail pengawal yang berkaitan app/Http/Controllers/PostController.php. 🎜
@can('delete', $post)
    <!-- Display delete link here... -->
@endcan
Salin selepas log masuk
Salin selepas log masuk
🎜Dalam kebanyakan kes, anda akan menggunakan kaedah membenarkan atau menolak (Gate</ / kod> rupa) untuk membenarkan operasi tertentu. Dalam contoh di atas, kami menggunakan kaedah <code class="inline">allows untuk menyemak sama ada pengguna semasa dapat melakukan operasi update-post. 🎜 🎜Pengguna yang bermata helang akan menyedari bahawa kami hanya menghantar parameter kedua $post kepada penutupan. Parameter pertama ialah pengguna yang sedang log masuk, yang disuntik secara automatik oleh fasad Gate. 🎜 🎜Beginilah cara anda harus menggunakan get untuk membenarkan tindakan dalam aplikasi Laravel anda. Jika anda ingin melaksanakan keizinan untuk model anda, bahagian seterusnya menerangkan cara menggunakan dasar. 🎜 🎜Dasar🎜 🎜Seperti yang kita bincangkan sebelum ini, apabila anda ingin mengelompokkan operasi kebenaran secara logik untuk mana-mana model atau sumber tertentu, perkara yang anda perlukan ialah dasar. 🎜

Cara membuat dasar tersuai

🎜Dalam bahagian ini, kami akan membuat dasar untuk model Post yang akan membenarkan semua operasi CRUD. Saya mengandaikan anda telah melaksanakan model Post dalam aplikasi anda jika tidak, sesuatu yang serupa akan dilakukan. 🎜 🎜Arahan artisan Laravel ialah kawan baik anda semasa membuat kod stub. Anda boleh menggunakan perintah artisan berikut untuk mencipta strategi bagi model Post. 🎜 rrreee 🎜Seperti yang anda lihat, kami menyediakan parameter --model=Post supaya ia mencipta semua kaedah CRUD. Jika tidak, ia mewujudkan kelas dasar kosong. Anda boleh menemui kelas dasar yang baru dibuat dalam app/Policies/PostPolicy.php. 🎜 rrreee 🎜Mari kita gantikan dengan kod berikut. 🎜 rrreee 🎜Untuk dapat menggunakan kelas strategi kami, kami perlu mendaftarkannya dengan penyedia perkhidmatan Laravel, seperti yang ditunjukkan dalam coretan kod berikut. 🎜 rrreee 🎜Kami telah menambahkan pemetaan dasar dalam atribut $policies. Ia memberitahu Laravel untuk memanggil kaedah dasar yang sesuai untuk membenarkan operasi CRUD. 🎜

您还需要使用 registerPolicies 方法注册策略,就像我们在 boot 方法中所做的那样。

没有模型的策略方法

PostPolicy 策略类中的 create 方法仅采用单个参数,这与采用两个参数的其他模型方法不同。一般来说,第二个参数是模型对象,您将在执行授权时使用它。但是,在 create 方法的情况下,您只需要检查是否允许相关用户创建新帖子。

在下一节中,我们将了解如何使用自定义策略类。

如何使用我们的自定义策略类

更进一步,让我们在 routes/web.php 文件中创建几个自定义路由,以便我们可以在那里测试我们的策略方法。

Route::get('service/post/view', 'PostController@view');
Route::get('service/post/create', 'PostController@create');
Route::get('service/post/update', 'PostController@update');
Route::get('service/post/delete', 'PostController@delete');
Salin selepas log masuk
Salin selepas log masuk

最后,让我们在 app/Http/Controllers/PostController.php 创建一个关联的控制器。

<?php
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use App\Post;
use Illuminate\Support\Facades\Auth;
 
class PostController extends Controller
{
  public function view()
  {
    // get current logged in user
    $user = Auth::user();
     
    // load post
    $post = Post::find(1);
     
    if ($user->can('view', $post)) {
      echo "Current logged in user is allowed to update the Post: {$post->id}";
    } else {
      echo 'Not Authorized.';
    }
  }
 
  public function create()
  {
    // get current logged in user
    $user = Auth::user();
 
    if ($user->can('create', Post::class)) {
      echo 'Current logged in user is allowed to create new posts.';
    } else {
      echo 'Not Authorized';
    }
 
    exit;
  }
 
  public function update()
  {
    // get current logged in user
    $user = Auth::user();
 
    // load post
    $post = Post::find(1);
 
    if ($user->can('update', $post)) {
      echo "Current logged in user is allowed to update the Post: {$post->id}";
    } else {
      echo 'Not Authorized.';
    }
  }
 
  public function delete()
  {
    // get current logged in user
    $user = Auth::user();
     
    // load post
    $post = Post::find(1);
     
    if ($user->can('delete', $post)) {
      echo "Current logged in user is allowed to delete the Post: {$post->id}";
    } else {
      echo 'Not Authorized.';
    }
  }
}
Salin selepas log masuk
Salin selepas log masuk

您可以通过不同的方式使用策略来授权您的操作。在上面的示例中,我们使用 User 模型来授权我们的 Post 模型操作。

User 模型提供了两种有用的授权方法 — cancantcan 方法用于检查当前用户是否能够执行某个操作。而与 can 方法对应的 cant 方法,用于判断动作是否无法执行。

让我们从控制器中获取 view 方法的片段,看看它到底做了什么。

public function view()
{
  // get current logged in user
  $user = Auth::user();
   
  // load post
  $post = Post::find(1);
   
  if ($user->can('view', $post)) {
    echo "Current logged in user is allowed to update the Post: {$post->id}";
  } else {
    echo 'Not Authorized.';
  }
}
Salin selepas log masuk
Salin selepas log masuk

首先,我们加载当前登录的用户,这为我们提供了 User 模型的对象。接下来,我们使用 Post 模型加载示例帖子。

接下来,我们使用 User 模型的 can 方法来授权 Post 模型的 view 操作。 can 方法的第一个参数是您要授权的操作名称,第二个参数是您要授权的模型对象。

这是如何使用 User 模型通过策略授权操作的演示。或者,如果您在控制器中授权某个操作,则也可以使用控制器助手。

…
$this->authorize('view', $post);
…
Salin selepas log masuk
Salin selepas log masuk

如您所见,如果您使用控制器助手,则无需加载 User 模型。

如何通过中间件使用策略

或者,Laravel 还允许您使用中间件授权操作。让我们快速查看以下代码片段,了解如何使用中间件来授权模型操作。

Route::put('/post/{post}', function (Post $post) {
    // Currently logged-in user is allowed to update this post.... 
})->middleware('can:update,post');
Salin selepas log masuk
Salin selepas log masuk

在上面的示例中,它将使用 can 中间件。我们传递两个参数:第一个参数是我们想要授权的操作,第二个参数是路由参数。根据隐式模型绑定的规则,第二个参数会自动转换为 Post 模型对象,并作为第二个参数传递。如果当前登录的用户无权执行 update 操作,Laravel 将返回 403 状态代码错误。

如何将策略与刀片模板结合使用

如果您希望在登录用户被授权执行特定操作时显示代码片段,您还可以在刀片模板中使用策略。让我们快速看看它是如何工作的。

@can('delete', $post)
    <!-- Display delete link here... -->
@endcan
Salin selepas log masuk
Salin selepas log masuk

在上述情况下,它只会向有权对 Post 模型执行删除操作的用户显示删除链接。

这就是您可以使用的策略概念,在授权模型或资源时它非常方便,因为它允许您将授权逻辑分组在一个地方。

只需确保您不会将门和策略一起用于模型的相同操作,否则会产生问题。这就是我今天的内容,今天就到此为止!

结论

今天,Laravel 授权占据了我文章的中心位置。在文章的开头,我介绍了 Laravel 授权、网关和策略的主要要素。

接下来,我们创建了自定义门和策略,以了解它在现实世界中的工作原理。我希望您喜欢这篇文章,并在 Laravel 环境中学到了一些有用的东西。

对于刚刚开始使用 Laravel 或希望通过扩展来扩展您的知识、网站或应用程序的人,我们在 Envato Market 上提供了多种可供您学习的内容。

Atas ialah kandungan terperinci Pintu dan strategi dalam Laravel. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!