基于不在动词上的值的授权

时间:2014-01-04 12:49:57

标签: laravel laravel-4

我正在基于不在动词上的值实现授权过程。

示例:

  • 允许所有用户/群组更新数据库字段
  • admin 可以将状态设置为所有可能的值(已确认|待处理|已取消)
  • 供应商可以设置为“已确认”

我找到的所有示例都围绕着能够插入,更新或删除某些内容的用户/组。

有什么东西可以处理开箱即用的情况,或者这是硬编码的吗?

1 个答案:

答案 0 :(得分:1)

基本上您需要的是在任何应用程序中难以维护的东西:细化权限。

您可以使用Cartalyst's Sentry轻松实现此功能。我是这样做的:

我的所有路线都按层次结构组织并命名为:

<?php

Route::get('login',      array('as'=>'logon.login',     'uses'=>'LogonController@login'));
Route::get('logged/out', array('as'=>'logon.loggedOut', 'uses'=>'LogonController@loggedOut'));

Route::group(array('before' => 'auth'), function()
{
    Route::get('logout',     array('as'=>'logon.logout',    'uses'=>'LogonController@logout'));

    Route::group(array('before' => 'permissions'), function()
    {
        Route::get('store/checkout/shipping/address',   array('as'=>'store.checkout.shipping.address',  'uses'=>'StoreController@shippingAddress'));
        Route::get('store/checkout/payment/confirmed',  array('as'=>'store.checkout.payment.confirmed', 'uses'=>'StoreController@confirmed'));
        Route::get('profile',                           array('as'=>'profile.show',                     'uses'=>'ProfileController@show'));
    });
});

过滤器'权限'下的用户可以检查用户是否有权使用它们:

Route::filter('permissions', function()
{
    $name = Route::current()->getName();
    $name =  'system' . ( ! empty($name) ? '.' : '') . $name;

    if (!Permission::has($name)) {
        App::abort(401, 'You are not authorized to access route '.$name);
    }
});

基本上我在这里得到当前路线名称,添加'系统'。它,并检查用户是否具有此特定权限。

以下是我创建群组和填充权限的方法:

<?php

public function seedPermissions()
{
    DB::table('groups')->truncate();

    $id = 1;

    Sentry::getGroupProvider()->create(array(
        'id' => $id++,
        'name'        => 'Super Administrators',
        'permissions' => array(
            'system' => 1,
        ),
    ));

    Sentry::getGroupProvider()->create(array(
        'id' => $id++,
        'name'        => 'Administrators',
        'permissions' => array(
            'system.users' => 1,
            'system.products' => 1,
            'system.store' => 1,
            'system.profile' => 1,
        ),
    ));

    Sentry::getGroupProvider()->create(array(
        'id' => $id++,
        'name'        => 'Managers',
        'permissions' => array(
            'system.products' => 1,
            'system.store' => 1,
            'system.profile' => 1,
        ),
    ));

    Sentry::getGroupProvider()->create(array(
        'id' => $id++,
        'name'        => 'Users',
        'permissions' => array(
            'system.store.checkout' => 1,
            'system.profile' => 1,
        ),
    ));
}

因此,如果用户尝试添加一些送货地址,路由'store.checkout.payment.confirmed',因为每个用户都可以访问'system.store.checkout',该路线内的所有内容都可供他使用。

这就是我检查权限的方式:

public static function has($permission)
{
    $all = [];
    $parts = explode('.',$permission);
    $permission = '';

    foreach($parts as $part) {
        $permission .= (!empty($permission) ? '.' : '') . $part;
        $all[] = $permission;
    }

    return Sentry::check() and Sentry::getUser()->hasAnyAccess($all);
}

它基本上建立了一个路线列表:

system
system.store
system.store.checkout
system.store.checkout.payment
system.store.checkout.payment.confirmed

如果Sentry在用户细化权限中找到其中一个,则返回true。

现在我只需要将用户添加到群组:

Sentry::findUserById(1)->addGroup( Sentry::getGroupProvider()->findByName('Users') );

如果我需要对特定用户/权限进行细化,我只需要:

$user = Sentry::findUserById(1);
$user->permissions['store.checkout.payment'] = false;
$user->save();

并且用户将永远无法再次在商店中支付任何费用。 :)