作者:ollie read 翻译:柳华芳

用户认证是一个web应用的重要部分,很多时候这是开发系统的第一步。laravel是一个强大、易用的框架,可以提供给你一些基本工具来根据你的需求创建简单的ACL(访问控制列表)。

我看到很多laravel包有这个功能,但是发现大多数过去复杂,通常不需要那么多。在此文章里,我将详细介绍如何创建一个简单但高度可定制的ACL,并且只使用基本的laravel工具。

让我们从头开始吧

laravel路由系统是我见到的最好的之一,允许你来创建资源型路由、restful路由、或基本路由。一个易被忽视的是路由的命名。作为一个标准联系,我命名过程中用到的每一个路由,下面是一个例子。

<?php

Route::group(array('prefix' => 'user'), function() {

    // for account registration
    Route::post('register', array(
        'as'    => 'user.register',
        'uses'  => 'UserController@register'
    ));

    // for authorising/logging in
    Route::post('authorise', array(
        'as'    => 'user.authorise',
        'uses'  => 'UserController@authorise'
    ));

    // check that a token is valid
    Route::get('validate', array(
        'as'    => 'user.validate',
        'uses'  => 'UserController@validate'
    ));

});

你将看到我们有三个不同的路由,将提供一些基本的功能。这里不去详细解读每一处,因为这不是我们的目的。

这些路由都有一个名字属性(as),意味着我有一个独立的专属路由,不受参数影响。条件是你的路由有明确的、唯一的名字,你有相应的基本权限。

权限匹配

现在,我们有独立命名的路由,我们需要一种匹配和配置用户当前权限的方法。还有,这里建设你已经有了user model 和用户数据表。

ACL通常拥有两个基本组件,他们是组和权限。一个用户将属于一个组或多个组,并且多个权限将属于一个组,并允许轻松的权限匹配(不单独为某一个用户添加权限配置)。

为了练习,我们将创建四个简单的表单。一个为组,一个为权限,一个为用户和组匹配,一个组和权限匹配。我们用laravel migration迁移工具来创建。

Groups-组

php artisan migrate:make create_acl_groups_table
acl-groups-migration.php  保存于migration目录下
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateAclGroupsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create(‘acl_groups’, function ($table) {
$table->increments(‘id’);
$table->string(‘name’, 50);
$table->string(‘description’, 255);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop(‘acl_groups’);
}
}

Permissions- 权限

php artisan migrate:make create_acl_permissions_table
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateAclPermissionsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create(‘acl_permissions’, function ($table) {
$table->increments(‘id’);
$table->string(‘ident’, 255);
$table->string(‘description’, 255);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop(‘acl_permissions’);
}
}
 acl-permissions-migration.php

User Groups 用户组

php artisan migrate:make create_acl_user_groups_table
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateAclUserGroupsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create(‘acl_user_groups’, function ($table) {
$table->integer(‘user_id’, false);
$table->integer(‘group_id’, false);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop(‘acl_user_groups’);
}
}
 acl-user-groups-migration.php

Group Permissions 组权限

php artisan migrate:make create_acl_group_permissions_table
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateAclGroupPermissionsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create(‘acl_group_permissions’, function ($table) {
$table->integer(‘group_id’, false);
$table->integer(‘permission_id’, false);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop(‘acl_group_permissions’);
}
}
 acl-group-permissions-migration.php

最后,在命令行项目所在目录执行下面命令:

php artisan migrate

使用数据库

现在,我们创建并运行我们的migrations,我们需要一个方法访问这些表。本文,我们将用Eloquent,这是laravel 默认的ORM。

让我们开始 AclGroup模块。

<?php
class AclGroup extends Eloquent {
protected $table = ‘acl_groups’;
protected $fillable = array(
‘name’, ‘description’
);
public $timestamps = false;
public function users()
{
return $this->belongsToMany(‘User’, ‘acl_user_groups’);
}
public function permissions()
{
return $this->belongsToMany(‘AclPermission’, ‘acl_group_permissions’);
}
}
model-group.php

这是一个标准的model. 你需要为你的model加入响应关系.

让我们添加 AclPermission model.

<?php
class AclPermission extends Eloquent {
protected $table = ‘acl_permissions’;
protected $fillable = array(
‘ident’, ‘description’
);
public $timestamps = false;
public function groups()
{
return $this->belongsToMany(‘AclGroup’, ‘acl_group_permissions’);
}
public function getKey()
{
return $this->attributes[‘ident’];
}
}
model-permission.php

这些大多数你能看明白,可能对getKey() 方法不熟悉. 这是让我们用一个集合来验证一个模块,通过 ident.

 

实施一切.

我们已经安装了数据库,已经得到获取这个信息的方法,现在我们需要做的是实施。此时,你可能希望路由来显示结果,但是你会发现还需要一些补充。

基于用户权限,最简单地访问当前页的方法是用过滤器,我们可以在路由中加入过滤器。

<?php
Route::filter(‘acl.permitted’, ‘AclPermittedFilter’);
Route::group(array(‘prefix’ => ‘user’), function() {
// other routes here
Route::get(‘supersecret’, array(
‘before’ => [‘auth’, ‘acl.permitted’],
‘as’ => ‘user.supersecret’,
‘uses’ => ‘UserController@supersecret’
))
});
routes-filtered.php

这里,我们已经在 ‘acl.permitted’ 下添加了过滤器,并且通过before属性添加到了路由,但是,你可以通过组功能来更简单地添加过滤器。你可以声明,我已经添加了auth过滤器到路由,来确保用户已经登录。

我们的 AclPermittedFilter 类 可以创建在任何位置, 只要laravel能自动加载到.

<?php
class AclPermittedFilter {
public function filter($route, $request)
{
$permitted = false;
$user = Auth::user();
$user->load(‘groups’, ‘group.permissions’);
foreach($user->groups as $group) {
if($group->permissions->has($route->getName())) {
$permitted = true;
break;
}
}
if(!$permitted) {
return Redirect::route(‘user.denied’);
}
}
}
 filter.php

到此时,我们浏览器访问/user/supersecret,只要他们有supersecret权限才能访问。

最后.

你可以写关于其他权限的控制函数.你甚至可以写任何函数在controller里,只要运行 AclPermittedFilter@filter 方法

3 Comments
  1. 学习分享

  2. 匿名 5年 ago

    请问 $user->load(‘groups’, ‘group.permissions’); 这里的User模型如何配置?

    • 柳华芳 5年 ago

      一般情况不需要配置模型,只需要在controller里定义函数就可以了

Leave a reply

电子邮件地址不会被公开。 必填项已用*标注

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.

联系

微信ruinews360 微信公众号:小芳侠

Sending

Log in with your credentials

Forgot your details?