【问题标题】:Laravel middleware for control user access to datas用于控制用户访问数据的 Laravel 中间件
【发布时间】:2019-07-04 01:06:42
【问题描述】:

我正在使用这种用户级别结构:

Company Owner
- Group Manager
-- Unit Manager
---Employee

我需要控制用户访问数据库中的数据。员工只能访问他存储的数据。单位经理也可以访问他自己的数据和他的员工的数据。组管理员可以访问整个组的数据。公司所有者可以访问所有内容。

我有一些这样的控制器:

class ClientController extends Controller
{
        public function index()
        {
            return Client::all();
        }
        // ...
}

在 Laravel 中,在某些控制器中控制对数据(不是控制器)的访问的最佳实践是什么,但不是在所有控制器中?这是解决这个问题的好方法吗?

【问题讨论】:

  • 使用角色和权限的概念。如果你想让自己更轻松,这里有一些适合你的包。 github.com/spatie/laravel-permissiongithub.com/Zizaco/entrust
  • 很好的提示,但我怎么知道用户只能看到他存储的数据?
  • 您可以在表格中创建created_byupdated_by 列以指示创建数据的人员..然后根据这些列检索数据。

标签: laravel laravel-5 data-access-layer laravel-middleware


【解决方案1】:

您可以为每个角色创建一个中间件,然后在您的 web.php 文件中,使用路由组来分配对用户可以访问的路由的访问权限。所以对于一个员工和部门经理都可以访问的路由,你传递两个中间件,对于那些只有组经理可以访问的,你只需传递组经理。

Route::group(['middleware' => ['auth', 'group-manager','unit-manager']], 
function() {
  Route::get('client','ClientController@index'); 
});

【讨论】:

  • 每个用户都可以访问客户端控制器。不同的是他们在那里看到的东西。我怎么说“员工”只能看到他存储的数据?
  • 对于这种情况,这只是一个查询问题。如果您存储数据,则应存储对放入数据的用户的引用。用户的 ID。当您调用数据时,您会在数据库中查询放置数据的人的 ID 与登录用户 ID 相同的文件。因此,对于每个文件存储,您的 dB 中都有一个输入,该输入将引用该文件。或者,您对每个用户使用唯一的文件结构。
  • 没有文件,只有数据库中的数据。 user_id 存储到记录中。是的,这是一个查询问题:) 问题是:如果我知道user_id,我可以找到他的下属,但是我想找到一种方法,我可以找出什么可以看到用户。如果他是销售人员,他只能看到他的记录。如果他是单位经理,他可以看到自己的数据,以及他所有的员工数据。但是我有很多控制器,我不想复制这个过滤器代码。有没有办法在一个地方定义它,并在我需要的地方使用它?
  • 在模型中定义。 laravel.com/docs/5.7/eloquent-mutators#defining-a-mutator 去那里作为参考。
【解决方案2】:

在路线中。所有中间件的好地方。

Route::get('/', function () {  ...  })->middleware('web');

【讨论】:

    【解决方案3】:

    中间件是访问控制的正确位置。对于组中间件,您可以通过这种格式使用

    Route::group(['middleware' => ['role:Company Owner']], function() {
        Route::get('/', 'AdminController@welcome');
        Route::get('/manage', ['middleware' => ['permission:manage-admins'], 'uses' => 'AdminController@manageAdmins']);
    });
    Route::group(['middleware' => ['role:Employee']], function() {
        Route::get('/', 'AdminController@welcome');
        Route::get('/manage', ['middleware' => ['permission:manage-admins'], 'uses' => 'AdminController@manageAdmins']);
    });
    

    单程

    Route::put('post/{id}', function ($id) {
        //
    })->middleware('role:Employee');
    

    您可以使用包进行用户角色基础访问控制

    https://github.com/Zizaco/entrust

    【讨论】:

      【解决方案4】:

      也许问题不够清楚,但我找到了解决方案:

      <?php
      
      namespace App\Scopes;
      
      use Illuminate\Database\Eloquent\Scope;
      use Illuminate\Database\Eloquent\Model;
      use Illuminate\Database\Eloquent\Builder;
      
      use Auth;
      use App\User;
      
      class DataAccessScope implements Scope
      {
          /**
           * Apply the scope to a given Eloquent query builder.
           *
           * @param  \Illuminate\Database\Eloquent\Builder  $builder
           * @param  \Illuminate\Database\Eloquent\Model  $model
           * @return void
           */
          public function apply(Builder $builder, Model $model)
          {
              // find the actual user
              $user_id = Auth::user()->id;
              $user = User::find( $user_id );
      
              // get all employees
              $employees = $user->allEmployeeFlatten();
      
              // get only the employee's ids
              $user_ids = $employees->pluck('id');
      
              // add current user's id too
              $user_ids->push( $user_id );
      
              // add the condition to every sql query
              $builder->whereIn('user_id', $user_ids);
          }
      }
      

      这是User模型的allEmployeeFaletten()函数:

      public function allEmployeeFlatten() {
          $employees = new Collection();
      
          foreach ( $this->employee()->get() as $employee ) {
              $employees->push( $employee );
      
              // run only if the user is on a leader level
              if ( $employee->user_role_id != 5 ) {
                  $employees = $employees->merge( $employee->allEmployeeFlatten() );
              }
          }
      
          return $employees;
      }
      

      每次我使用该范围时,此范围都会为所有 SQL 查询添加一个条件。

      【讨论】:

        猜你喜欢
        • 2018-07-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-24
        相关资源
        最近更新 更多