Проблема Laravel с безопасностью на странице профиля

#angular #laravel #authentication #jwt #middleware

Вопрос:

У меня уже некоторое время возникают проблемы с моим сайтом в Laravel. У меня есть интерфейс Angular, и я использую api для запроса данных конкретного пользователя, чтобы конкретный пользователь мог изменить свои данные на странице своего профиля. С учетом сказанного я, очевидно, не хочу, чтобы посторонние люди могли переходить на другие страницы профиля, чтобы также изменять свои данные.

Например: На моей странице с помощью URL .../user/1 -адреса пользователь может запросить свои данные. Проблема в следующем: если вы измените 1 , .../user/1 .../user/2 например, вход на, человек сможет получить доступ к данным человека с идентификатором 2 .

Я попробовал следующее: В моем api.php :

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

// Get Specific User
Route::get('user/{id}' ,'AppHttpControllersUserController@getUserById')->middleware('auth');
 

Неавторизованные пользователи больше не могут получить доступ к странице профиля, но все авторизованные пользователи могут получить доступ ко всем другим пользователям и изменить их данные.

Я также попытался: $id = Auth::id() , но это возвращает мне попытку прочитать свойство «id» на null

Проблема кажется мне довольно сложной, так как мне каким-то образом нужен идентификатор пользователей, которые в настоящее время вошли в систему, и убедитесь, что они не могут получить доступ к идентификатору других пользователей. У тебя есть какие-нибудь идеи, как мне лучше всего это сделать?

Я использую Laravel 8

Большое спасибо!

Редактировать

Спасибо вам за подробный ответ, вы подарили мне надежду. Я сделал все так, как ты описал.

Сначала я создал php artisan make:middleware ResourceOwner промежуточное программное обеспечение и инициализировал его Kernel.php в защищенном $routeMiddleware следующим образом: 'ResourceOwner' => AppHttpMiddlewareResourceOwner::class, и вставил функцию, как вы описали.

Но, к сожалению, сейчас я получаю 401 (Несанкционированный), независимо от того, какой идентификатор я передаю и с каким пользователем я вошел в систему. Я пытался:

 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, я передаю идентификатор пользователя в качестве идентификатора, имеет ли это какое-либо отношение к этому?

Но в моей базе данных мой пользователь объявлен как идентификатор, например: $table->id(); . К сожалению, я все еще слишком неопытен, чтобы сказать, может ли это иметь какое-то отношение к сообщению об ошибке. Я использую пакет Tymon/jwt-auth.

Еще раз большое спасибо за ваше время и усилия, я действительно ценю это.

Комментарии:

1. Вы используете паспорт для аутентификации?

2. Нет, на самом деле я использую пакет Tymon/jwt-auth.

3. 1 — Удалите ResourceOwner промежуточное программное обеспечение из kernel.php , в противном случае вы прямо говорите, что оно должно использоваться на каждом маршруте. 2 — Согласно документам, вы можете получить своего пользователя, сделав auth()->user() это, я бы попытался получить идентификатор с помощью auth()->user()->id

4. Я удалил его только что, и я получаю следующую ошибку: «Целевой класс [Владелец ресурсов] не существует. и несанкционированная ошибка. Но когда я использую Postman, я получаю следующую ошибку: ** Маршрут [вход] не определен**. Может ли проблема быть связана с этим?

5. Когда я удаляю функцию внутри ResourceOwner.php Я все еще получаю сообщение об ошибке Несанкционированно , поэтому я думаю, что функция даже не может быть вызвана? Но это все еще сбивает с ->middleware(['auth', 'ResourceOwner']); толку, так как определено после моего маршрута.

Ответ №1:

ИМО, вы должны использовать /users маршруты в отношении CRUD пользователей и /profile маршрут для редактирования пользовательских данных.

В любом случае, есть простой способ достичь того, что вам нужно, с помощью промежуточных программ. Допустим, вы хотите разрешить использовать маршрут ТОЛЬКО в том случае, если {id} параметр совпадает с параметром аутентифицированного пользователя.

Вы можете создать очень простое промежуточное программное обеспечение, т. е. ResourceOwner

 <?php

namespace AppHttpMiddleware;

use Closure;

class ResourceOwner
{
    /**
     * Handle an incoming request.
     *
     * @param  IlluminateHttpRequest  $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 AppHttpMiddlewareResourceOwner;

Route::get('user/{id}' ,'AppHttpControllersUserController@getUserById')->middleware(['auth:api', ResourceOwner::class]);

 

Комментарии:

1. Большое вам спасибо за ваш замечательный ответ и ваше время! Я отредактировал свой вопрос, я был бы очень признателен, если бы вы могли заглянуть в мой вопрос в разделе РЕДАКТИРОВАНИЕ .

2. Привет, Лучано, это снова я. После нашего разговора я снова сел на несколько часов и, наконец, нашел проблему. Мне просто нужно было изменить в вашей функции условие !== на != и тогда, наконец, Почтальон справился с этим правильно. Большое спасибо за ваши усилия и время, редко можно встретить такого замечательного человека!

3. И полная функция была такой: дескриптор публичной функции($запрос, закрытие $next) { $пользователь = аутентификация()->пользователь(); если ($запрос->>идентификатор != $пользователь->>>идентификатор) { прервать(403, «Несанкционированное действие.»); } еще { вернуть $next($запрос); } }

4. Рад это слышать! Я обновил свой ответ в соответствии с вашим окончательным решением

Ответ №2:

Авторизация может быть сложной задачей, но, к счастью, Laravel поставляется с несколькими инструментами, которые помогут вам.

Одним из них является политика, которая позволяет вам контролировать, кто может просматривать/хранить/обновлять/удалять ресурсы (например, ваши пользователи).

Полная документация по авторизации очень хорошо охватывает эту тему: https://laravel.com/docs/8.x/authorization


Тем не менее, в данном конкретном случае — пользователь — вы могли бы сделать что-то подобное auth/me , чтобы показать профиль аутентифицированного пользователя (без передачи в id качестве параметра).

Как всегда, есть много способов сделать то же самое, и в конечном итоге все зависит от вашего проекта, вашего опыта, ваших целей…

Комментарии:

1. Спасибо вам за ответ и ваше время. Вы правы, мне следует еще раз взглянуть на документацию. Как новичку, мне все еще довольно трудно понять эту концепцию с аутентификацией. Я буду стараться изо всех сил!