作者: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
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’);
}
}
|
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’);
}
}
|
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’);
}
}
|
最后,在命令行项目所在目录执行下面命令:
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. 你需要为你的model加入响应关系.
让我们添加 AclPermission model.
这些大多数你能看明白,可能对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’
))
});
|
这里,我们已经在 ‘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’);
}
}
}
|
到此时,我们浏览器访问/user/supersecret,只要他们有supersecret权限才能访问。
最后.
你可以写关于其他权限的控制函数.你甚至可以写任何函数在controller里,只要运行 AclPermittedFilter@filter 方法
学习分享
请问 $user->load(‘groups’, ‘group.permissions’); 这里的User模型如何配置?
一般情况不需要配置模型,只需要在controller里定义函数就可以了