Laravel 个人资料页面存在安全问题
Laravel issue with security in profile page
我在 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()
,但是这个returns我Attempt to read 属性 "id" on null
这个问题在我看来相当复杂,因为我不知何故需要当前登录用户的 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 包 .
再次感谢您的时间和精力,我真的很感激。
授权可能具有挑战性,但幸运的是,Laravel 提供了多种工具来帮助您。
其中之一是允许您控制谁可以 view/store/update/delete 资源(例如您的用户)的策略。
关于授权的完整文档很好地涵盖了这个主题:https://laravel.com/docs/8.x/authorization
也就是说,对于这种特定情况 - 用户 - 你可以 做类似 auth/me
的事情来显示经过身份验证的用户的个人资料(不通过 id
作为参数)。
一如既往,有很多方法可以做同样的事情,最终这完全取决于您的项目、您的经验、您的目标...
IMO,你应该使用 /users
路由来处理用户的 CRUD 和 /profile
路由来编辑用户数据。
无论如何,有一个简单的方法可以用中间件实现你所需要的。
假设您希望仅在 {id}
参数与经过身份验证的用户相同时才允许使用路由。
您可以创建一个非常基本的中间件 IE ResourceOwner
<?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]);
我在 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()
,但是这个returns我Attempt to read 属性 "id" on null
这个问题在我看来相当复杂,因为我不知何故需要当前登录用户的 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 包 .
再次感谢您的时间和精力,我真的很感激。
授权可能具有挑战性,但幸运的是,Laravel 提供了多种工具来帮助您。
其中之一是允许您控制谁可以 view/store/update/delete 资源(例如您的用户)的策略。
关于授权的完整文档很好地涵盖了这个主题:https://laravel.com/docs/8.x/authorization
也就是说,对于这种特定情况 - 用户 - 你可以 做类似 auth/me
的事情来显示经过身份验证的用户的个人资料(不通过 id
作为参数)。
一如既往,有很多方法可以做同样的事情,最终这完全取决于您的项目、您的经验、您的目标...
IMO,你应该使用 /users
路由来处理用户的 CRUD 和 /profile
路由来编辑用户数据。
无论如何,有一个简单的方法可以用中间件实现你所需要的。
假设您希望仅在 {id}
参数与经过身份验证的用户相同时才允许使用路由。
您可以创建一个非常基本的中间件 IE ResourceOwner
<?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]);