Laravel 个人资料页面中的安全问题

Posted

技术标签:

【中文标题】Laravel 个人资料页面中的安全问题【英文标题】:Laravel issue with security in profile page 【发布时间】:2021-11-23 09:57:26 【问题描述】:

一段时间以来,我在 Laravel 中的网站一直存在问题。我有一个 Angular 前端,我正在使用 api 来查询特定用户的数据,以便特定用户可以在他的个人资料页面中更改他的数据。话虽如此,我显然不希望未经授权的人也能够访问其他个人资料页面来更改他们的数据。

例如: 在我的页面上,用户可以使用 URL .../user/1 查询他的数据。这样做的问题是:如果将.../user/1中的1更改为.../user/2,例如,该人可以访问id为2的人的数据。

我尝试了以下操作: 在我的api.php

Route::middleware('auth:api')->get('/user', function (Request $request) 
    return $request->user();
);

// Get Specific User
Route::get('user/id' ,'App\Http\Controllers\UserController@getUserById')->middleware('auth');

未经授权的用户无法再访问个人资料页面,但所有授权用户都可以访问所有其他用户并更改他们的数据。

我也尝试过:$id = Auth::id(),但这返回了我尝试在 null 上读取属性“id”

在我看来,这个问题相当复杂,因为我不知何故需要当前登录用户的 ID,并确保他们无法访问其他用户 ID。你知道我怎样才能最好地做到这一点吗?

我正在使用 Laravel 8

非常感谢!

编辑

谢谢你的详细解答,你给了我希望。我按照你的描述做了一切。

首先我使用php artisan make:middleware ResourceOwner 中间件创建并在protected $routeMiddleware 下的Kernel.php 中初始化它:'ResourceOwner' => \App\Http\Middleware\ResourceOwner::class, 并按照您描述的那样放入函数。

但不幸的是,我现在得到 401(未经授权),无论我通过什么 ID 以及我使用哪个用户登录。我试过了:

1. auth('api')->user(); 
2. $request->user('api'); 
3. Auth::guard('api')->user()

但它们都没有奏效。你知道我错过了什么吗? 我还注意到,当我删除您描述的功能时:

public function handle($request, Closure $next)

    if ($request->id !== auth('api')->user->id) 
        abort(403);
    

    return $next($request);

我仍然收到同样的错误401(未经授权)

但是当我对我的 JWT 进行编码时,我将 user_id 作为 ID 传递,这与它有什么关系吗?

但在我的数据库中,我的用户被声明为 id,例如:$table->id();。不幸的是,我仍然太缺乏经验,无法说出这是否与错误消息有关。我使用 Tymon/jwt-auth 包

再次感谢您的时间和精力,我真的很感激。

【问题讨论】:

您是否使用护照进行身份验证? 不,实际上我使用的是 Tymon/jwt-auth 包。 1 - 从kernel.php 中删除ResourceOwner 中间件,否则您明确表示必须在每个路由中使用它。 2 - 根据文档,您可以通过 auth()->user() 获取您的用户,所以我会尝试使用 auth()->user()->id 获取 id 我刚刚删除了它,我收到以下错误:“目标类 [ResourceOwner] 不存在。Unauthorized 错误。但是当我使用 Postman 我收到以下错误:** Route [login] not defined**。问题是否与此有关? 当我删除ResourceOwner.php里面的函数时,我仍然得到错误Unauthorized,所以我认为这个函数甚至不能被调用?但它仍然令人困惑,因为->middleware(['auth', 'ResourceOwner']); 是在我的路线之后定义的。 【参考方案1】:

IMO,您应该使用 /users 路由来处理用户的 CRUD,并使用 /profile 路由来编辑用户的数据。

无论如何,有一种简单的方法可以通过中间件实现您所需要的。 假设您希望仅当 id 参数与经过身份验证的用户相同时才允许使用路由。

你可以创建一个非常基础的中间件IEResourceOwner

<?php

namespace App\Http\Middleware;

use Closure;

class ResourceOwner

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    
        $user = auth()->user();
        if ($request->id != $user->id) 
            abort(403);
        

        return $next($request);
    

中间件会检查传入的id参数是否与登录的用户相同,如果不是,则中止抛出403错误响应。

为了使用这个中间件,你可以将它添加到你的路由中

use App\Http\Middleware\ResourceOwner;

Route::get('user/id' ,'App\Http\Controllers\UserController@getUserById')->middleware(['auth:api', ResourceOwner::class]);

【讨论】:

非常感谢您的精彩回答和您的宝贵时间!我已经编辑了我的问题,如果您能在 EDIT 下查看我的问题,我将不胜感激。 你好卢西亚诺,又是我。经过我们的交谈,我又坐了几个小时,终于找到了问题所在。我只需要在您的函数中将条件 !== 更改为 != ,然后 Postman 最终正确处理了它。非常感谢您的努力和时间,难得遇到这么棒的人! 完整的功能是这样的: public function handle($request, Closure $next) $user = auth()->user(); if ($request->id != $user->id) abort(403, '未经授权的操作。'); 其他 返回 $next($request); 很高兴听到这个消息!我已根据您的最终解决方案更新了我的答案【参考方案2】:

授权可能具有挑战性,但幸运的是,Laravel 提供了多种工具来帮助您。

其中之一是允许您控制谁可以查看/存储/更新/删除资源(例如您的用户)的政策。

关于授权的完整文档很好地涵盖了这个主题:https://laravel.com/docs/8.x/authorization


话虽如此,对于这种特定情况 - 用户 - 您可以执行类似 auth/me 的操作,显示经过身份验证的用户的个人资料(不传递 id 作为参数)。

与往常一样,有很多方法可以做同样的事情,最终这一切都取决于你的项目、你的经验、你的目标......

【讨论】:

感谢您的回答和您的时间。你是对的,我应该再看看文档。作为一个初学者,我仍然觉得很难通过身份验证来理解这个概念。我会努力的!

以上是关于Laravel 个人资料页面中的安全问题的主要内容,如果未能解决你的问题,请参考以下文章

刀片模板中的Laravel重定向问题

请教Express 中的 session 和 cookie 的安全问题

在没有提供 API 密钥的情况下访问 Laravel 中的数据库有多安全?

如何在同一个 laravel 应用程序上通过 laravel 护照安全地使用 axios

如何解决“Facebook 检测到 MyApp 未使用安全连接传输信息。” Laravel 中的错误

Laravel 隐藏属性。例如密码 - 安全