高效 / 权限控制器
AuthorityController 是一个适用于 Laravel 5 的 PHP 授权库,用于限制特定用户可以访问的资源。
Requires
- php: >=5.5.9
- authority-php/authority-laravel: ~2.4.3
Requires (Dev)
- laravelcollective/html: 5.2.*
- mockery/mockery: 0.9.*
- orchestra/testbench: ~3.2.0
- phpunit/phpunit: ~4.5
README
AuthorityController 是一个适用于 Laravel 5.3 的 PHP 授权库,用于限制特定用户可以访问的资源。
所有权限定义在一个位置
config/authority-controller.php
并在控制器、路由、视图和数据库查询中不会重复。
关于对 Laravel 5.2 的支持,请参阅 AuthorityController 2.2 分支
关于对 Laravel 5.0 或 5.1 的支持,请参阅 AuthorityController 2.1 分支
关于对 Laravel 4.1 或 4.2 的支持,请参阅 AuthorityController 1.2 分支
演示应用程序
您可以通过这个 Laravel 5.3 演示应用程序 看到该包的实际应用。
来源和灵感
这是 authority-laravel
包的一个扩展。
Authority 端口了 CanCan 的一些功能,而这个包端口了 几乎所有 其他功能。
安装
使用 Composer
- 将
authority-controller
包添加到您的composer.json
文件中,以要求 AuthorityController
composer require efficiently/authority-controller:dev-master
- 将服务提供者添加到
config/app.php
Efficiently\AuthorityController\AuthorityControllerServiceProvider::class,
- 将别名(外观)添加到您的 Laravel 应用配置文件中
'Params' => Efficiently\AuthorityController\Facades\Params::class, 'Authority' => Efficiently\AuthorityController\Facades\Authority::class,
- 这将允许您通过您习惯于使用 Laravel 组件的静态接口来访问 Authority 类。
Authority::can('update', SomeModel::class);
配置
创建角色和权限表
我们提供了一种基本的表结构,帮助您开始创建自己的角色和权限。
将它们发布到您的迁移目录或直接复制。
php artisan vendor:publish --provider="Efficiently\AuthorityController\AuthorityControllerServiceProvider" --tag="migrations"
运行迁移
php artisan migrate
这将创建以下表
- roles
- role_user
- permissions
要利用这些表,您可以将以下方法添加到您的 User
模型中。您还需要创建 Role 和 Permission 模型占位符(将 App\Authority\
替换为您自己的命名空间)。
//app/User.php public function roles() { return $this->belongsToMany(Authority\Role::class)->withTimestamps(); } public function permissions() { return $this->hasMany(Authority\Permission::class); } public function hasRole($key) { $hasRole = false; foreach ($this->roles as $role) { if ($role->name === $key) { $hasRole = true; break; } } return $hasRole; }
//app/Authority/Role.php <?php namespace App\Authority; use Illuminate\Database\Eloquent\Model; class Role extends Model {}
//app/Authority/Permission.php <?php namespace App\Authority; use Illuminate\Database\Eloquent\Model; class Permission extends Model {}
初始化资源过滤器和控制器方法
在您的 app/Http/Controllers/Controller.php
文件中,添加 ControllerAdditions
特性并禁用 AuthorizesRequests
特性
<?php namespace App\Http\Controllers; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Routing\Controller as BaseController; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Efficiently\AuthorityController\ControllerAdditions as AuthorityControllerAdditions; class Controller extends BaseController { // use AuthorizesRequests; use DispatchesJobs, ValidatesRequests; use AuthorityControllerAdditions; //code... }
注意:如果您确实需要默认的 Laravel 授权系统,您可以使用 AuthorizesRequests
特性,如果将它的 authorize
和 authorizeResource
方法别名化,如下所示
<?php //code... class Controller extends BaseController { use DispatchesJobs, ValidatesRequests; use AuthorizesRequests, AuthorityControllerAdditions { AuthorityControllerAdditions::authorize insteadof AuthorizesRequests; AuthorizesRequests::authorize as illuminateAuthorize; AuthorizesRequests::authorizeResource as illuminateAuthorizeResource; } //code... }
入门
AuthorityController 期望 auth()->user()
返回当前已认证的用户。现在,默认情况下 Laravel 5 处理这个问题。
定义权限规则
用户权限在 AuthorityController 的配置文件中定义。
您可以使用以下命令发布 AuthorityController 的默认配置文件
php artisan vendor:publish --provider="Efficiently\AuthorityController\AuthorityControllerServiceProvider" --tag="config"
这将把配置文件的副本放置在 config/authority-controller.php
。该配置文件包含一个 initialize
函数,这是设置规则和别名的绝佳位置。
//config/authority-controller.php <?php $serializer = new SuperClosure\Serializer; return [ 'initialize' => $serializer->serialize(function ($authority) { $user = auth()->guest() ? new App\User : $authority->getCurrentUser(); // Action aliases. For example: $authority->addAlias('moderate', ['read', 'update', 'delete']); // Define abilities for the passed in user here. For example: if ($user->hasRole('admin')) { $authority->allow('manage', 'all'); } else { $authority->allow('read', 'all'); } }) ];
请参阅定义权限规则 获取详细信息。
检查权限规则和授权
然后,您可以使用视图和控制器中的 Authority::can()
和 Authority::cannot()
方法检查当前用户的权限。
@if (Authority::can('update', $article))
{{ link_to_route("articles.edit", "Edit", $article->id) }}
@endif
请参阅检查权限规则 获取更多信息
如果用户无法执行指定的操作,控制器中的 authorize()
方法将抛出异常。
public function show($id) { $this->article = App\Article::find($id); $this->authorize('read', $this->article); }
为每个操作设置此功能可能会很繁琐,因此提供了 loadAndAuthorizeResource()
方法来自动授权 RESTful 风格资源控制器中的所有操作。它将使用前置过滤器将资源加载到实例变量中并为其每个操作授权。
<?php namespace App\Http\Controllers; class ArticlesController extends Controller { public function __construct() { $this->loadAndAuthorizeResource(); } public function show($id) { // $this->article is already loaded and authorized } }
请参阅授权控制器操作 获取更多信息。
异常处理
当在控制器中调用 authorize()
并用户无法执行指定的操作时,会抛出 Efficiently\AuthorityController\Exceptions\AccessDenied
异常。可以可选地提供一条消息。
Authority::authorize('read', 'App\Product', 'Unable to read this product.');
您可以在 app/Exceptions/Handler.php
文件的 render()
方法中捕获异常并修改其行为。例如,在这里我们将错误消息设置为闪存并重定向到主页。
//app/Exceptions/Handler.php /** * Render an exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @param \Exception $e * @return \Illuminate\Http\Response */ public function render($request, Exception $e) { //code... if ($e instanceof \Efficiently\AuthorityController\Exceptions\AccessDenied) { $msg = $e->getMessage(); \Log::error('Access denied! '.$msg); return redirect('/home')->with('flash_alert', $msg); } return parent::render($request, $e); } //code...
请参阅异常处理 获取更多信息。
文档
Wiki 文档
权限文档
权限 介绍。
Authority-Laravel 通用用法。
CanCan Wiki 文档
因为 AuthorityController 是 CanCan 的移植版本,您还可以阅读 CanCan 的 Wiki 文档这里。
控制器扩展
现在您的控制器具有一个 $params
属性
<?php namespace App\Http\Controllers; class ProductsController extends Controller { //code... public function update($id) { $this->params['id'] == $id;//-> true $this->params['product'];//-> ["name" => "Best movie"] $this->params['controller'];//-> 'products' $this->params['action'];//-> 'update' //code... } //code... }
更新日志
#### 2.3.0-dev
- 支持 Laravel 5.3!
#### 2.2.0
- 支持 Laravel 5.2!
#### 2.1.1
- 更新 Laravel >= 5.1.11 的安装说明
#### 2.1.0
- 支持 Laravel 5.1!
2.0.1
- 用
laravelcollective/html
包替换已弃用的包illuminate/html
- 自动加载迁移类已无用,请参阅问题 #30(由 @Fnatte 提出)
- 现在仅在 Composer 的开发模式下自动加载来自
tests
目录的类,以避免冲突
#### 2.0.0
- 支持 Laravel 5.0!
- 使用您的 Laravel 别名来解析模型命名空间名称。
- 或者自动猜测它们,例如
User
=>App\User
- 添加一个新的配置选项
controllerClass
,默认值为Illuminate\Routing\Controller
- 在 Parameters 类中支持路由模型绑定。参见:[https://laravel.net.cn/docs/5.0/routing#route-model-binding](https://laravel.net.cn/docs/5.0/routing#route-model-binding) 和问题 [https://github.com/efficiently/authority-controller/issues/21](https://github.com/efficiently/authority-controller/issues/21)
- 使用 authority-laravel 包代替 authority-l4。
- 升级说明(如果您之前使用过此包与 Laravel 4)
- 将您的
authory-controller
配置文件从app/config/packages/efficiently/authority-controller/config.php
移动到config/authority-controller.php
- 发布
authory-controller
迁移文件(参见本 README 中的 创建角色和权限表 部分)
- 将您的
1.2.4
- 添加
BaseController::flushAuthorityEvents()
静态方法。对于 Codeception 中的功能测试非常有用(参见问题 #14 和 此 Wiki 页面 了解更多信息)。 - 修复 User::hasRoles() 方法以避免重复角色。
1.2.3
- 遵循 PSR-2 编码风格
1.2.2
- 使用 Laravel 4.2 运行测试
1.2.1
- 修复
composer.json
文件。
1.2.0
- 安全修复:当存在实际实例对象时,条件回调从未被评估。
- 不兼容向下:否定规则覆盖先前规则,允许规则不覆盖先前规则,而是进行逻辑或操作(修复 #5)。与
authority-php\authority
包相比,更接近 CanCan 默认行为。有关更多信息,请参阅 Wiki 文档:[https://github.com/efficiently/authority-controller/wiki/Authority-Precedence](https://github.com/efficiently/authority-controller/wiki/Authority-Precedence) - 支持 PHP 5.4、5.5、5.6 和 HipHop 虚拟机 (hhvm)。
- 更新
Parameters
类,允许自定义路由使用id
和parent_id
路由参数(修复 #6)。
1.1.3
- 将 Authority-L4 包升级以修复 Laravel 4.1 支持。
1.1.2
- 调整模拟系统,该系统模拟 Eloquent 的构造函数方法。
1.1.1
- 在控制器中减少侵入性的参数注入
- 检查当前解析的控制器是否响应 paramsBeforeFilter 方法。否则,应用程序会崩溃。
- 使用当前 Laravel 应用程序的 Controller 别名而不是硬编码的类名。
1.1.0
- Laravel 4.1 兼容性的第一个 beta 版本。
- 不兼容 Laravel 4.0。
1.0.0
- 第一个稳定版本,仅兼容 Laravel 4.0。
- 有关 Laravel 4.1 支持,请参阅 [https://github.com/efficiently/authority-controller/tree/1.1](https://github.com/efficiently/authority-controller/tree/1.1) 的 AuthorityController 1.1 分支。
- 修复 AccessDenied 类,当异常消息为空时,未回退到默认消息。
0.10.0
- 不兼容向下:
Params::get('controller')
的行为现在类似于 Rails。它返回蛇形小写的控制器名称,并以复数形式返回。
0.9.0
- 第一个 beta 版本
缺少的功能
- 在
ControllerResource
类中,使用在User
模型中使用的#load_collection
方法。看起来很复杂。相反,使用具有collectionScope
选项的特定查询作用域,在您的集合(例如index
)控制器操作中过滤您的数据。因为您将通过角色允许/拒绝访问或检查集合中每条记录的用户授权来允许/拒绝访问。 - 在
Ability
类中,存在一个#attributes_for
方法。与Authority
一起使用时看起来没有用,因为规则条件只能通过Closure
而不是关联数组来实现。CanCan 只处理#attribute_for
的Hash
(关联数组)条件。 ControllerAdditions
中的#skip_*
方法。- 对于
Authority
的allow()
和deny()
方法,第三个参数不是一个可选的包含条件的哈希(关联数组),而是一个匿名函数(Closure)。
$authority->allow('update', 'App\Product', function ($self, $product) { return $product->available === true; });
注意事项
兼容性
它**只**与 PHP >= 5.6 和 Laravel >= 5.3 框架兼容。
CanCan 和 AuthorityController 之间的区别
请参阅 Wiki 页面 CanCan 和 AuthorityController 之间的区别
哲学
它遵循 D.R.W.J.P.I. 原则
不要重新发明轮子,只需移植!-- (c) 2013 A.D.
问题或问题?
如果您对 AuthorityController 有任何问题,请添加一个 GitHub 上的 issue 或将该项目进行分支并提交一个 pull request。
要运行测试,您应该安装 PHPUnit 并运行 phpunit tests
。
特别感谢
AuthorityController 受 CanCan 的强烈启发,并使用 Authority-Laravel。