szykra/laravel-guard

Laravel 5 的简单易用角色和权限系统(ACL)。

0.1.2 2015-07-25 21:48 UTC

This package is auto-updated.

Last update: 2024-09-12 20:05:46 UTC


README

version codeclimate license

简单易用的 Laravel 5 角色 和 权限 系统 (ACL)

Laravel Guard 是一个用于轻松控制对系统各部分访问的包。它提供了简单的工具来保护您的路由和检查权限的用户方法。

安装

使用 composer 安装

将依赖项添加到您的 composer.json 文件中并运行 composer update

"szykra/laravel-guard": "~0.1.0"

配置

创建新迁移以存储角色和权限

目前 Guard 将所有关于角色和权限的信息存储在数据库中。

Schema::create('roles', function(Blueprint $table)
{
    $table->increments('id');
    $table->string("tag", 20);
    $table->string("name", 100);
});

Schema::create('permissions', function(Blueprint $table)
{
    $table->increments('id');
    $table->string("tag", 50);
    $table->string("name", 50);
    $table->string("description");
});

Schema::create('permission_role', function(Blueprint $table)
{
    $table->increments('id');
    $table->unsignedInteger('role_id');
    $table->unsignedInteger('permission_id');

    $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
    $table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade');
});

当然,您应该在您的 users 表中添加新字段以将用户与 role 链接起来。

Schema::update('users', function(Blueprint $table)
{
    $table->unsignedInteger('role_id');

    $table->foreign('role_id')->references('id')->on('roles');
});

配置您的 User 模型

Guard 提供了新的 contract - Permissible。它需要两个方法

  • is($role)
  • can($action)

别担心!Guard 有一个实现了这些方法的特质。您需要做的就是使用它并将新的关系添加到 roles

User 模型

use Szykra\Guard\Contracts\Permissible;
use Szykra\Guard\Traits\Permissions;

class User extends Model implements Permissible, AuthenticatableContract, CanResetPasswordContract {

	use Permissions, Authenticatable, CanResetPassword;

    public function role()
    {
        return $this->belongsTo('Szykra\Guard\Models\Role');
    }

}

Guard 为您的应用程序提供了两个新的模型 - RolePermission。别担心它们 - 这些是用于从数据库检索信息所必需的。

将服务提供者添加到您的配置中

打开您的 config/app.php 文件并将此行添加到 $providers 数组中

'Szykra\Guard\GuardServiceProvider'

现在 Permissible 接口绑定到当前登录用户。您可以通过 IoC 容器 在任何需要的地方注入它,但请记住 - 如果您未登录,则应用程序会抛出 绑定异常。始终使用此接口与 auth 中间件一起使用!

注册新中间件

打开您的 app/Http/Kernel.php 并将此行添加到 $middleware 数组中

'Szykra\Guard\Middleware\ProtectRoutes',

如果您不想保护所有路由,则可以将此中间件注册为 $routeMiddleware 并仅在特定路由中使用它。

'guard' => 'Szykra\Guard\Middleware\ProtectRoutes'

角色和权限

Guard 提供了 角色权限 的管理,但这究竟意味着什么呢?

在复杂的系统中,我们有多种类型的用户,例如管理员、经理、用户或版主。这些类型被称为 角色。用户可以在系统中执行许多操作,但特定类型的用户应具有特定的权利,称为 权限。当用户拥有一个角色时,他们也将拥有与该角色相关的权限。我们可以检查这些权限以阻止或允许特定的操作。

权限命名约定

Guard 未定义您应该如何命名您的权限。尽量保持它 简单简短一致易于记忆。我非常喜欢使用简单的表示法 RESOURCE.ACTION,例如 USERS.READUSERS.UPDATE。您可以根据自己的命名约定进行操作,例如 read usersupdate user。选择权在您手中!

创建角色和权限

您有很多方法可以创建 角色权限。您可以将数据手动插入数据库,创建特殊的 Seeder 以准备数据或使用 artisan Guard 命令 在需要时创建 角色权限 条目。

使用 Artisan CLI 创建

Guard 提供了新的 artisan 命令

  • guard:grant role permission
  • guard:make:role tag [name]
  • guard:make:permission tag [name]

要创建新的角色,请运行以下命令

php artisan guard:make:role ADMIN Administrator

创建新权限

php artisan guard:make:permission USERS.READ

要创建权限并将其即时链接到角色,请使用--role选项。

php artisan guard:make:permission USERS.CREATE -r ADMIN

要链接现有角色与权限,请使用guard:grant命令。

php artisan guard:grant ADMIN USERS.READ

使用Seeder创建。

如果您有大量角色和权限,则使用Seeder是一个不错的选择,例如。

use Szykra\Guard\Models\Permission;
use Szykra\Guard\Models\Role;
use Illuminate\Database\Seeder;

class GuardTableSeeder extends Seeder
{
    public function run()
    {
        $roles = [
            'ADMIN'  => 'Administrator',
            'EDITOR' => 'Content Editor'
        ];

        $permissions = [
            ['tag' => 'POSTS.CREATE', 'name' => 'Create posts', 'description' => 'Ability to create new post'],
            ['tag' => 'POSTS.READ', 'name' => 'Read posts', 'description' => 'Ability to read posts data'],
            ['tag' => 'POSTS.UPDATE', 'name' => 'Update posts', 'description' => 'Ability to update posts data'],
            ['tag' => 'POSTS.DELETE', 'name' => 'Delete posts', 'description' => 'Ability to delete posts']
        ];

        $permModels = [];

        foreach ($permissions as $perm) {
            $permModels[$perm['tag']] = Permission::create($perm);
        }

        $rolesToPerm = [
            'ADMIN'  => ['POSTS.CREATE', 'POSTS.READ', 'POSTS.UPDATE', 'POSTS.DELETE'],
            'EDITOR' => ['POSTS.CREATE', 'POSTS.READ', 'POSTS.UPDATE']
        ];

        foreach ($rolesToPerm as $tag => $permissions) {
            $name = $roles[$tag];
            $role = Role::create(compact('tag', 'name'));

            foreach ($permissions as $perm) {
                $role->permissions()->save($permModels[$perm]);
            }
        }
    }
}

用法

路由保护

要保护您的路由,请在路由数组中定义键needs

/* String */
$router->get('/users', [
	'as' => 'users.index',
	'uses' => 'UsersController@index',
	'needs' => 'USERS.READ'
]);

/* As array */
$router->get('/users/{id}', [
	'as' => 'users.show',
	'uses' => 'UsersController@show',
	'needs' => ['USERS.READ']
]);

您可以为单个路由要求更多权限。

/* String - separate by pipe */
$router->post('/users', [
	'as' => 'users.store',
	'uses' => 'UsersController@store',
	'needs' => 'USERS.READ|USERS.CREATE'
]);

/* As array */
$router->put('/users', [
	'as' => 'users.update',
	'uses' => 'UsersController@update',
	'needs' => ['USERS.READ', 'USERS.CREATE']
]);

如果您将Guard定义为$routeMiddleware,则必须添加middleware操作。

$router->put('/users', [
	'as' => 'users.update',
	'uses' => 'UsersController@update',
	'needs' => ['USERS.READ', 'USERS.CREATE'],
	'middleware' => 'guard'
]);

当然,您可以按所需权限分组您的路由。

$router->group(['needs' => ['USERS.READ']], function() use ($router)
{
    // Needs USERS.READ permission
    $router->get('/users/{id}', [
        'as' => 'users.show',
        'uses' => 'UsersController@show',
    ]);

    // Needs USERS.READ and USERS.UPDATE permissions
    $router->put('/users/{id}', [
        'as' => 'users.update',
        'uses' => 'UsersController@update',
        'needs' => ['USERS.UPDATE']
    ]);
});

检查权限

您在用户模型中有两个新方法用于检查权限。

  • $user->can($action)
  • $user->is($role)

要获取用户实例,请使用Laravel的Auth外观或将其注入到您的类中。

注入到构造函数

use Szykra\Guard\Contracts\Permissible;

class UsersController extends Controller {

    public function __construct(Permissible $user)
    {
        $this->user = $user;
    }

    public function update(Request $request, $id)
    {
        if( ! $this->user->can('USERS.UPDATE')) {
            // redirect, exception, flash message, etc.
        }

        // do something with user
    }

}

注入到操作

use Szykra\Guard\Contracts\Permissible;

class UsersController extends Controller {

    public function destroy(Permissible $user, $id)
    {
        if( ! $user->can('USERS.DELETE')) {
            // redirect, exception, flash message, etc.
        }

        // destroy user
    }

}

通过Auth外观检索用户

您可以在拥有当前认证用户实例的地方检查权限,例如通过Auth::user()。这在视图中非常有用,当您必须只为具有特定权限的用户渲染视图的一部分时。

<section class="actions">
    <a href="{{ route('users.show', $user->id) }}">Show</a>

    @if(Auth::user()->can('USERS.EDIT'))
        | <a href="{{ route('users.edit', $user->id) }}">Edit</a>
    @endif
</section>

表单请求中检查权限

Laravel 5表单请求是检查权限的好地方。请参见以下示例。

use Szykra\Guard\Contracts\Permissible;

class CreateUserRequest extends Request {

	public function authorize(Permissible $user)
	{
		return $user->can("USERS.CREATE");
	}

	public function rules()
	{
        return [
            // your validation rules
        ];
	}

}

当用户权限不足时的反应

如果用户权限不足,则Guard抛出InsufficientPermissionException。您可以捕获它并返回视图、重定向或其他操作。

要全局捕获此异常,请使用您的ExceptionHandler,例如app/Exception/Handler.php中的render()方法。

public function render($request, Exception $e)
{
    if($e instanceof InsufficientPermissionException) {
        Flash::warning("Insufficient permissions", "You don't have enough permission to access to this section.");

        return redirect()->route('home');
    }

	return parent::render($request, $e);
}

许可证

MIT许可证。版权所有©2015 Szymon Krajewski。