#php #reactjs #laravel #cors
#php #reactjs #laravel #cors
Вопрос:
Только начинаю с barryvdh/laravel-cors
. У меня есть серверное приложение, запущенное на порту 8000, которое аутентифицирует пользователей через Laravel Passport, и мой react.js клиентское приложение, запущенное на порту 3000. Прямо сейчас я пытаюсь заставить действие «войти» работать.
От клиента, когда я предоставляю правильные учетные данные, токен отправляется обратно, а статус равен 200. Когда учетные данные недействительны, возвращается 401. Пока все хорошо. Однако, если я предоставляю только электронное письмо в форме и без пароля, я получаю следующую ошибку, связанную с CORS:
При возникновении ошибки происходят следующие сетевые вызовы:
Мой логин на стороне клиента:
login = (email, password) => {
console.log(email);
fetch("http://localhost:8000/api/auth/login", {
method: 'POST',
body: JSON.stringify({
'email': email,
'password': password
}),
headers: {
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then(response => {
console.log(response['access_token']); //with correct credentials this is logged out and set in local storage
localStorage.setItem('access_token', response['access_token']);
})
.catch(error => console.error('Error: ', error));
}
На стороне сервера:
public function login(Request $request)
{
$request->validate([
'email' => 'required|string|email',
'password' => 'required|string',
'remember_me' => 'boolean'
]);
$credentials = request(['email', 'password']);
if(!Auth::attempt($credentials)) {
return response()->json([
'message' => 'Unauthorized'
], 401);
}
$user = $request->user();
$tokenResult = $user->createToken('Personal Access Token');
$token = $tokenResult->token;
if ($request->remember_me) {
$token->expires_at = Carbon::now()->addWeeks(1);
}
$token->save();
return response()->json([
'access_token' => $tokenResult->accessToken,
'token_type' => 'Bearer',
'expires_at' => Carbon::parse(
$tokenResult->token->expires_at
)->toDateTimeString()
]);
}
cors.php
(опубликовано из пакета barryvdh / laravel-cors):
return [
'supportsCredentials' => false,
'allowedOrigins' => ['*'],
'allowedOriginsPatterns' => [],
'allowedHeaders' => ['*'],
'allowedMethods' => ['*'],
'exposedHeaders' => [],
'maxAge' => 0,
];
api.php
:
Route::group(['prefix' => 'auth',], function () {
Route::post('login', 'AuthController@login');
Route::post('register', 'AuthController@register');
Route::get('register/activate/{token}', 'AuthController@registerActivate');
Route::group(['middleware' => 'auth:api'], function() {
Route::get('logout', 'AuthController@logout');
Route::get('user', 'AuthController@user');
});
});
Kernel.php
:
protected $middlewareGroups = [
'web' => [
AppHttpMiddlewareEncryptCookies::class,
IlluminateCookieMiddlewareAddQueuedCookiesToResponse::class,
IlluminateSessionMiddlewareStartSession::class,
// IlluminateSessionMiddlewareAuthenticateSession::class,
IlluminateViewMiddlewareShareErrorsFromSession::class,
AppHttpMiddlewareVerifyCsrfToken::class,
IlluminateRoutingMiddlewareSubstituteBindings::class,
],
'api' => [
BarryvdhCorsHandleCors::class,
'throttle:60,1',
'bindings',
],
];
protected $middleware = [
BarryvdhCorsHandleCors::class,
AppHttpMiddlewareCheckForMaintenanceMode::class,
IlluminateFoundationHttpMiddlewareValidatePostSize::class,
AppHttpMiddlewareTrimStrings::class,
IlluminateFoundationHttpMiddlewareConvertEmptyStringsToNull::class,
AppHttpMiddlewareTrustProxies::class
];
Отправляя тот же POST-запрос (один на /api/auth/login
с исключенным паролем) через postman, я получаю ожидаемое сообщение об ошибке:
{
"message": "The given data was invalid.",
"errors": {
"password": [
"The password field is required."
]
}
}
Но при выполнении этого через клиентское приложение react выдается ошибка на скриншоте. Я предполагаю, что это как-то связано с запросом ПАРАМЕТРОВ HTTP перед запуском, который браузер отправляет как часть работы CORS.
Как я могу это исправить? Я бы ожидал, что для статуса будет возвращен 401, а клиент react получит то же сообщение JSON, которое получает Postman в случае, если пароль пуст. Просто кажется странным, что на основе полезной нагрузки для этого запроса POST возникает ошибка, связанная с CORS. Означает ли это, что сервер и / или клиент неправильно настраивают CORS?
Комментарии:
1. Как laravel, так и react app должны правильно отправлять заголовки CORS. Если вы можете избежать перенаправления CORS, это значительно упрощает работу
2. Я думал, что только серверная сторона должна устанавливать заголовки, связанные с CORS. Какие заголовки необходимо установить на стороне клиента? Я не думаю, что смогу избежать перенаправления CORS
3. на данный момент кажется отличным, не могли бы вы также добавить
config/app.php
контент и раздел промежуточных программ в свойKernel.php
?4. я вижу, что
BarryvdhCorsHandleCors::class,
это объявлено в обоих$middleware
и$middlewareGroups
, можете ли вы попробовать удалить его из$middlewareGroups
раздела, еще одна вещь, я заметил, что у многих людей возникает эта проблема, и, похоже, это связано с версией пакета, какую версию вы используете? Взгляните на эти проблемы: link1 , link25. пожалуйста, я добавлю это в качестве ответа.
Ответ №1:
Похоже, что ошибка возникает при возникновении ошибки в вашем серверной части.
Как упоминалось в документах :
При возникновении ошибки промежуточное программное обеспечение запускается не полностью. Поэтому, когда это произойдет, вы не увидите фактического результата, но вместо этого получите ошибку CORS.
Эта проблема помогла определить источник ошибки
Ответ №2:
Прежде всего, член класса:
protected $middleware
Будет применяться промежуточное программное обеспечение как для api
, так и web
От laravel.com/docs/5.8/middleware#registering-middleware
Если вы хотите, чтобы промежуточное ПРОГРАММНОЕ обеспечение запускалось во время каждого HTTP-запроса к вашему приложению, укажите класс промежуточного программного обеспечения в свойстве $middleware вашего app/Http/Kernel.php класс.
Смотрите также: barryvdh/laravel-cors#глобальное использование
Поэтому попробуйте зарегистрировать свое промежуточное программное обеспечение один раз, удалив: BarryvdhCorsHandleCors::class
из вашей 'api'
группы промежуточного программного обеспечения.
И для логических целей выполните рефакторинг вашего protected $middleware
с:
protected $middleware = [
AppHttpMiddlewareCheckForMaintenanceMode::class,
IlluminateFoundationHttpMiddlewareValidatePostSize::class,
AppHttpMiddlewareTrimStrings::class,
IlluminateFoundationHttpMiddlewareConvertEmptyStringsToNull::class,
AppHttpMiddlewareTrustProxies::class,
BarryvdhCorsHandleCors::class,
];