rookwood/turnstile

基于策略的 ACL 对 Laravel 4.x 的支持

v0.1.0 2014-07-13 15:25 UTC

This package is not auto-updated.

Last update: 2024-09-24 01:46:13 UTC


README

Turnstile 是为 Laravel 4 设计的基于策略的 ACL 库,旨在提供非常精细的用户权限控制。这是通过将任何给定的用户操作映射到一个评估操作是否允许的策略类来实现的。这样做比简单的用户/角色系统提供了更多的控制(尽管角色在 Turnstile 中仍然很容易使用)。这种方法的优点是,同一个系统可以用于从保护管理面板到检查用户是否可以看到登录按钮(如果已经登录,则拒绝可见性访问等)的任何事情。

示例

由于之前没有人使用过博客示例,我们在这里演示一下

// CommentController.php (or somesuch)
if ($this->user->can("edit_comment", ['comment' => $comment]))
{
    // logic
}
else
{
    // pass back an error telling them why they were denied
}

edit_comment 操作映射到通过 PolicyProvider 的策略类。对于 edit_comment,我们在这个示例中将它映射到 CommentEditingPolicy

<?php namespace Vendor\Application\Policies;

// Abstract class enforcing the correct signature on the execute() method
use Rookwood\Turnstile\Policies\Policy;

class CommentEditingPolicy extends Policy {

    const UNSPECIFIED_FAILURE = "policy.comments.failure";
    const NOT_USERS_COMMENT   = "policy.comments.not_users_comment";
    const PAST_EDIT_DEADLINE  = "policy.comments.past_edit_deadline";

    public function execute($user, $data)
    {
        $comment = $data['comment'];

        if ($user->isAn('admin'))
        {
            return TRUE
        }

       if (time() > $comment->editTimeLimit)
       {
            return self::PAST_EDIT_DEADLINE;
       }

       if ($user->owns($comment))
       {
            return TRUE;
       }
       else
       {
            return self::NOT_USERS_COMMENT
       }
    }
}

如您所见,策略可以出于任何原因拒绝权限,并提供一个具体的错误消息说明原因。我喜欢使用类常量来存储可以稍后传递给 Lang::get() 的消息键。额外的好处是易于翻译。

安装

1: 使用 composer 获取所有内容

"require" : {
    "rookwood/turnstile" : "dev-master"
}

2: 将 Rookwood\Turnstile\TurnstileServiceProvider 添加到 app/config/app.php 中服务提供商的列表

3: 发布配置并运行迁移。注意,在创建角色_user 连接表之前,必须先运行用户表迁移。它已经足够远地指向未来,只要您已经创建了用户表的迁移文件,这就不应该成为问题。

$ php artisan config:publish rookwood/turnstile
$ php artisan migrate --package="rookwood/turnstile"

4: 创建您的 PolicyProvider 文件(可以放在任何地方,只要自动加载器可以找到它)。

<?php namespace Wherever\You\Want\It;

use Rookwood\Turnstile\Policies\Provider\PolicyProvider as BaseProvider;

class PolicyProvider extends BaseProvider {

    public static $data = [
        // Add your policy mappings here
        "edit_comment" => "Rookwood\\Policies\\Comments\\CommentEditingPolicy",

        // etc
    ];
}

5: 编辑 config/packages/rookwood/turnstile/turnstile.php,将命名空间键指向您的提供者的命名空间。这样,PolicyServiceProvider 类就知道在哪里找到它了。

6: 让您的 User 模型使用 Rookwood\Turnstile\User\PolicyTrait

7: 确保任何必要的控制器都可以访问当前用户对象。我通常在构造函数中这样做

public function __construct()
{
    if (Auth::check())
    {
        $this->user = Auth::user();
    }
    else
    {
        $this->user = App::make('User');
    }
}

8: 在 app/config/app.php 中为 Role 添加一个别名为 Rookwood\Turnstile\User\Role。作为替代,您可以创建自己的 Role 类,只要您有与 User 类的 m:n 关系即可。如果您的 User 类是命名空间化的,也要对它做同样的事情。

用法

现在您已经完成了所有设置,实际上使用它相对简单。每当您想查看用户是否允许执行某项操作时,只需调用 $user->can('do_something', array('someData' => 'data needed for evaluation'))。这将返回一个布尔值。如果它是 False,您可以在 Rookwood\Turnstile\Policies\Policy::$policyFailureState 中获取策略发送的状态代码。可能有必要导入该命名空间并有一个单独的方法或类来处理失败。根据用户试图做什么,甚至可能有必要在响应头中设置 403 NOT AUTHORIZED。显然,对于尝试访问网站敏感区域的行为来说,这更有意义,而不是检查用户是否可以看到注册链接。

然后,你只需创建一个具有execute方法的策略类,让它返回TRUE或错误状态(见上面示例)。将操作名称和策略类添加到PolicyProvider中,你就可以开始了。

为您的User模型包含的PolicyTrait提供了一些有用的方法,以帮助您的策略类和用户角色

$user->owns($object)

测试用户和数据库中提供的对象之间是否存在关系

$user->isA($role)

测试用户是否具有特定的角色。对于像我这样的人,也提供了isAn(),以避免使用isA('admin')这样的表达

$user->addRole($role)

将一个角色添加到用户。可以传递一个角色名称的字符串或角色对象。也提供了removeRole($role)方法。