#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. Спасибо вам за ответ и ваше время. Вы правы, мне следует еще раз взглянуть на документацию. Как новичку, мне все еще довольно трудно понять эту концепцию с аутентификацией. Я буду стараться изо всех сил!