【问题标题】:Laravel: always adding user/{id} to routes or different methodLaravel:总是将用户/{id} 添加到路由或不同的方法中
【发布时间】:2016-06-13 19:36:30
【问题描述】:

我有一个 Laravel 应用程序。在路线文件中,我有

Route::group(['prefix' => 'user'], function () {
    Route::group(['middleware' => ['auth', 'roles'], 'roles' => ['buyer']], function() {
        Route::get('dashboard/buyer', ['as' => 'buyer_dashboard', 'uses' => 'User\Buyer\DashboardController@index']);
    });

    Route::group(['middleware' => ['auth', 'roles'], 'roles' => ['seller']], function() {
        Route::get('dashboard/seller', ['as' => 'seller_dashboard', 'uses' => 'User\Seller\DashboardController@index']);
    });

});

我有一个中间件,它基本上检查路由中提供的 id 是否与当前登录的用户相同。如果不是这种情况,我会返回一个错误页面。这样做的原因是我想防止用户可以访问另一个用户的仪表板。我还想防止用户可以为其他人出价(通过更改 http 请求中的 id)

问题在于,在第一条路由中,id 指的是用户。在第二条路线中,id 指的是批次 id。

我是否有义务将第二条路线更改为:

Route::get('{id}/lot/{lot}/bid/create', ['as' => 'buyer_lot_bid_create', 'uses' => 'User\Buyer\BidsController@create']);

第一个 id 指的是用户,以便我可以检查用户的 id?

或者是否有另一种方法可以防止用户访问其他用户页面而无需在路由中明确传递用户/{id}?

【问题讨论】:

  • 可以通过auth::user->id()查看登录用户的用户id;在你的代码中。不需要从http请求中获取。
  • 好吧,我知道 auth::user->id() 是当前登录的用户。但它没有捕捉到登录用户可以访问其他用户的内容的情况。假设 id 为 1 的用户已登录并可以通过 /user/1/dashboard 访问他自己的仪表板,那么他仍然可以访问 /user/2/dashboard。因此,我也在检查路线 {id}。你明白我的意思了吗?
  • 好的,所以在控制器函数中,您使用来自 url 的用户 ID,如果两者不相同,请尝试使用 auth::user->id() 检查它,然后使用重定向页面404 或 401 随意。
  • 确实在中间件中这样做。因此,这意味着所有路由都应始终以我不喜欢的 user/id 开头。我正在寻找一种隐式传递用户 ID 的方法。
  • 你不使用Gate有什么原因吗?

标签: laravel


【解决方案1】:

在中间件中这样做听起来是个坏主意。您已经遇到了中间件规则的一个例外,而且您肯定会遇到更多。

有两种方法可以做到这一点:

  1. 使用 laravel 内置的授权工具:https://laravel.com/docs/5.1/authorization

  2. 如果检查的是“路由中提供的 id,与当前登录的用户相同”,则根本不需要通过路由传递用户的 id。用户可以访问例如。 /dashboard/buyer 路由中没有参数。他们正在访问谁的仪表板?当然是登录用户之一。因此,用户甚至无法尝试访问其他用户的仪表板。出价也是如此。您可以设置bid 端点,这样投标人的 id 就不会通过路由传入 - 它只是在您的控制器方法中设置为登录用户的 id。再说一遍,甚至无法尝试代表其他用户出价。

【讨论】:

  • 谢谢。现在将尝试选项2。在选项 1 上,我正在使用 github.com/spatie/laravel-permission,但不确定它在这里如何派上用场?
  • 除非架构过于复杂,否则您不需要第三方,这似乎并不
  • 在这种情况下,github.com/spatie/laravel-permission 似乎不会提供任何比 Laravel 内置的 auth 有用的东西。但是,是的,无论如何,如果您只需要 2,那么 2 是一个更好的选择。
  • 是的,我已经更改了代码,因此我不需要传递用户 ID。我将路线文件添加到原始问题中。尽管我需要为买方(/user/dashboard/buyer)和卖方(user/dashboard/seller)提供单独的路线,但我仍然在苦苦挣扎,所以我可能决定检查控制器中的角色,但我不喜欢那样接近太多。同样为此,Cristo 的以下建议可能有效,但需要实施。完成后会报告。
【解决方案2】:
  class AuthServiceProvider extends ServiceProvider
    {
        public function boot(GateContract $gate)
        {
            $this->registerPolicies($gate);

            $gate->define('see-profile', function ($user, $profile) {
                return $user->id === $profile->user_id;
            });
        }

控制器:

public function profile($id)
{
    $post = Profile::findOrFail($id);
    if (Gate::denies('see-profile', $profile)) {
      abort(403);
    }
 }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-16
    • 2014-08-17
    • 2017-05-22
    • 2016-09-21
    • 1970-01-01
    • 2021-02-08
    • 2013-11-22
    相关资源
    最近更新 更多