darrylkuhn / enforce
使用Eloquent模型强制实施访问控制限制
Requires
- php: >=5.4.0
- illuminate/support: 4.x
- laravelbook/ardent: 2.x
Requires (Dev)
- illuminate/database: 4.x
Suggests
- zizaco/entrust: Role-based Permissions for Laravel 4
This package is not auto-updated.
Last update: 2024-09-24 00:50:13 UTC
README
Enforce是Laravel4的一个插件,它提供了一个优雅的方式来定义自定义数据访问执行器,用于您的Eloquent ORM模型。
快速入门
在composer.json
文件的require
键中添加以下内容
"darrylkuhn/enforce": "dev-master"
运行Composer更新命令
$ composer update
在config/app.php
中,将现有的'Eloquent'键替换为'Enforce\Model'
'aliases' => array( 'App' => 'Illuminate\Support\Facades\App', 'Artisan' => 'Illuminate\Support\Facades\Artisan', ... 'Eloquent' => 'Enforce\Model', ),
配置
Enforce使用标准的Laravel配置。创建app/config/enforce.php
,内容如下
<?php return [ 'byDefault' => false, ];
当然,如果您愿意,可以将此设置为true,但在这样做之前请阅读整个快速入门指南(有很好的理由在启用enforce之前初始化应用程序)。
使用方法
您的模型应继续扩展Eloquent。幕后它们实际上扩展了Enforce\Model,它反过来又扩展了\Illuminate\Database\Eloquent\Model。
您的模型现在继承了一些新的静态方法,包括enforceOnRead()和enforceFilter()。
enforceOnRead()
接受一个参数,即一个模型或集合。默认情况下,enforceOnRead()
不执行任何操作,它只是简单地返回传递给它的模型或集合,这是您添加自定义执行规则的地方。enforceFilter()
接受一个模型或集合,并过滤掉任何不符合指定键和值的模型。例如,如果您想确保当前认证的用户只能访问他们自己的用户模型,您可以使用以下代码实现这样的限制
<?php class User extends Eloquent { public static function enforceOnRead( $models ) { // If the user is not logged in then they can't read user data period if ( !Auth::check() ) { return null; } // Filter out any results that don't belong to the user else { $key = 'id'; $refrenceValue = Auth::user()->id; return self::enforceFilter($models, $key, $refrenceValue); } } }
这会过滤掉ID不匹配当前认证用户ID的所有模型。现在调用User::find($id);
将返回过滤后的结果。为了更有用,假设您想允许“管理员”访问所有模型,您可以实现以下代码
<?php class User extends Eloquent { public static function enforceOnRead( $models ) { // If the user is not logged in then they can't read user data period if ( !Auth::check() ) { return null; } // If our user isn't an admin then we need to be sure to // filter out any results that aren't theirs elseif ( ! Auth::user()->isAdmin() ) { $key = 'id'; $refrenceValue = Auth::user()->id; return self::enforceFilter($models, $key, $refrenceValue); } // Otherwise they can see anything. else { return $models; } } }
enforceFilter()
可以接受复杂的键(例如,$key = 'primaryCompany()->locations[0]->id';
可以正常评估)。
如果需要,您可以通过在调用中显式设置执行为false来绕过执行,例如User::find($id, ['*'], false);
启动
在某些情况下,在应用程序达到某些状态之前关闭执行可能是有利的。在上面的例子中,如果执行是开启的,并且我们没有在调用User::find()
时显式设置执行为false,认证过程将失败。这是因为规则要求一个有效的认证用户才能访问用户模型,而认证系统使用用户模型进行认证——鸡生蛋,蛋生鸡。有几种解决方法;当然,您可以在认证子系统中的调用上添加标记,但这可能需要修改Laravel核心(这不被推荐)。假设您在使用过滤器在路由之前认证用户,我的建议是使用执行关闭(byDefault => false
)初始化应用程序,然后在认证完成后添加一个过滤器将其切换为true。例如,在filters.php中添加以下过滤器
Route::filter('app.applyEnforce', function() { // Make sure our models enforce their access rules by default from here on out Config::set('enforce.byDefault', true); });
然后将其包含在适当的路由调用中
Route::group(array('before' => array('auth.basic', 'app.applyEnforce') ), function() { // User Management Route::resource('users/{id}/roles', 'UserRoleController', ['only' => ['index', 'store', 'delete', 'describe']]); });
这会首先认证用户,然后开启执行。