【发布时间】:2019-08-29 02:21:41
【问题描述】:
刚刚开始使用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' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
\Barryvdh\Cors\HandleCors::class,
'throttle:60,1',
'bindings',
],
];
protected $middleware = [
\Barryvdh\Cors\HandleCors::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\TrustProxies::class
];
通过邮递员发出相同的 POST 请求(向/api/auth/login 发送一个不包含密码的请求)我收到了预期的错误消息:
{
"message": "The given data was invalid.",
"errors": {
"password": [
"The password field is required."
]
}
}
但是,通过 react 客户端应用程序进行此操作,会引发屏幕截图中的错误。我猜这与浏览器作为 CORS 工作方式的一部分发送的预检 HTTP OPTIONS 请求有关。
我该如何纠正这个问题?我希望为状态返回 401,并让反应客户端在密码为空的情况下获得 Postman 收到的相同 JSON 消息。根据该 POST 请求的有效负载,出现与 CORS 相关的错误似乎很奇怪。这是否意味着服务器和/或客户端没有正确设置 CORS?
【问题讨论】:
-
laravel 和 react 应用都需要正确发送 CORS 头。如果您可以避免 CORS 重定向,那么处理起来会容易得多
-
我以为只有服务器端需要设置 CORS 相关的标头。客户端需要设置哪些标头?我认为我无法避免 CORS 重定向
-
在这一点上看起来很棒,您能否在您的
Kernel.php中添加config/app.php内容和中间件部分? -
不客气,我会添加这个作为答案。