在安装 tymon/jwt-auth 后的 laravel Backend REST API 应用程序中再次遇到 CORS 错误
Posted
技术标签:
【中文标题】在安装 tymon/jwt-auth 后的 laravel Backend REST API 应用程序中再次遇到 CORS 错误【英文标题】:In laravel Backend REST API app after installing tymon/jwt-auth again suffer CORS error 【发布时间】:2020-03-21 20:14:17 【问题描述】:我使用从 Laravel 后端 REST API 读取的数据制作 @vue/cli 4.0.5 / vuex 3 应用程序,并使用 /barryvdh/laravel-cors(0.11.4) 来解决 CORS 问题: 它工作正常,直到我添加了 tymon/jwt-auth(1.0.0) 并实现了这个库,我在包含的库中遇到了一些问题,但是在 我安装了它我又遇到了CORS错误,比如:
VM15:1 OPTIONS http://local-ctasks-api.com/api/login 403 (Forbidden)
(anonymous) @ VM15:1
dispatchXhrRequest @ xhr.js?b50d:172
xhrAdapter @ xhr.js?b50d:11
dispatchRequest @ dispatchRequest.js?5270:59
Promise.then (async)
request @ Axios.js?0a06:53
Axios.<computed> @ Axios.js?0a06:78
wrap @ bind.js?1d2b:9
eval @ index.js?4360:135
login @ index.js?4360:124
wrappedActionHandler @ vuex.esm.js?2f62:747
dispatch @ vuex.esm.js?2f62:438
boundDispatch @ vuex.esm.js?2f62:332
authenticate @ Login.vue?7463:164
submit @ Login.vue?2447:24
invokeWithErrorHandling @ vue.runtime.esm.js?2b0e:1854
invoker @ vue.runtime.esm.js?2b0e:2179
original._wrapper @ vue.runtime.esm.js?2b0e:6911
login:1 Access to XMLHttpRequest at 'http://local-ctasks-api.com/api/login' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
composer.json:
"name": "laravel/laravel",
"type": "project",
"description": "The Laravel Framework.",
"keywords": [
"framework",
"laravel"
],
"license": "MIT",
"require":
"php": "^7.1.3",
"barryvdh/laravel-cors": "^0.11.4",
"fideloper/proxy": "^4.0",
"laravel/framework": "^5.8.0",
"laravel/tinker": "^1.0",
"tymon/jwt-auth": "^1.0.0",
"wboyz/laravel-enum": "^0.2.1"
,
"require-dev":
"fzaninotto/faker": "^1.8",
"mockery/mockery": "^1.0",
"nunomaduro/collision": "^2.0",
"phpunit/phpunit": "^7.0"
,
"config":
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true
,
"extra":
"laravel":
"dont-discover": []
,
"autoload":
"psr-4":
"App\\": "app/"
,
"classmap": [
"database/seeds",
"database/factories"
]
,
"autoload-dev":
"psr-4":
"Tests\\": "tests/"
,
"minimum-stability": "dev",
"prefer-stable": true,
"scripts":
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi"
],
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"@php artisan key:generate --ansi"
]
app/Http/Kernel.php:
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\Barryvdh\Cors\HandleCors::class, // I ADDED THIS LINE !
];
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' => [
'throttle:60,1',
'bindings',
'cors', // ALSO I ADDED THIS LINE - fount in net!
],
];
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\Authenticate::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
];
在 config/auth.php 中:
<?php
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt', // LINE WITH JWT as driver !
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
],
'password_timeout' => 10800,
];
配置/cors.php:
<?php
return [
'supportsCredentials' => false,
'allowedOrigins' => ['*'],
'allowedHeaders' => ['Content-Type', 'X-Requested-With'],
'allowedMethods' => ['*'], // ex: ['GET', 'POST', 'PUT', 'DELETE']
'exposedHeaders' => [],
'maxAge' => 0,
];
在 config/app.php 中:
'providers' => [
/*
* Laravel Framework Service Providers...
*/
Illuminate\Auth\AuthServiceProvider::class,
Illuminate\Broadcasting\BroadcastServiceProvider::class,
Illuminate\Bus\BusServiceProvider::class,
Illuminate\Cache\CacheServiceProvider::class,
Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
Illuminate\Cookie\CookieServiceProvider::class,
Illuminate\Database\DatabaseServiceProvider::class,
Illuminate\Encryption\EncryptionServiceProvider::class,
Illuminate\Filesystem\FilesystemServiceProvider::class,
Illuminate\Foundation\Providers\FoundationServiceProvider::class,
Illuminate\Hashing\HashServiceProvider::class,
Illuminate\Mail\MailServiceProvider::class,
Illuminate\Notifications\NotificationServiceProvider::class,
Illuminate\Pagination\PaginationServiceProvider::class,
Illuminate\Pipeline\PipelineServiceProvider::class,
Illuminate\Queue\QueueServiceProvider::class,
Illuminate\Redis\RedisServiceProvider::class,
Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
Illuminate\Session\SessionServiceProvider::class,
Illuminate\Translation\TranslationServiceProvider::class,
Illuminate\Validation\ValidationServiceProvider::class,
Illuminate\View\ViewServiceProvider::class,
Barryvdh\Cors\ServiceProvider::class, // CORS ADDED LINE
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
// App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
// Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class, // I HAD PROBLEMS WITH THIS OPTION - SO I COMMENTED it
],
'aliases' => [
'App' => Illuminate\Support\Facades\App::class,
'Arr' => Illuminate\Support\Arr::class,
'Artisan' => Illuminate\Support\Facades\Artisan::class,
'Auth' => Illuminate\Support\Facades\Auth::class,
'Blade' => Illuminate\Support\Facades\Blade::class,
'Broadcast' => Illuminate\Support\Facades\Broadcast::class,
'Bus' => Illuminate\Support\Facades\Bus::class,
'Cache' => Illuminate\Support\Facades\Cache::class,
'Config' => Illuminate\Support\Facades\Config::class,
'Cookie' => Illuminate\Support\Facades\Cookie::class,
'Crypt' => Illuminate\Support\Facades\Crypt::class,
'DB' => Illuminate\Support\Facades\DB::class,
'Eloquent' => Illuminate\Database\Eloquent\Model::class,
'Event' => Illuminate\Support\Facades\Event::class,
'File' => Illuminate\Support\Facades\File::class,
'Gate' => Illuminate\Support\Facades\Gate::class,
'Hash' => Illuminate\Support\Facades\Hash::class,
'Lang' => Illuminate\Support\Facades\Lang::class,
'Log' => Illuminate\Support\Facades\Log::class,
'Mail' => Illuminate\Support\Facades\Mail::class,
'Notification' => Illuminate\Support\Facades\Notification::class,
'Password' => Illuminate\Support\Facades\Password::class,
'Queue' => Illuminate\Support\Facades\Queue::class,
'Redirect' => Illuminate\Support\Facades\Redirect::class,
'Redis' => Illuminate\Support\Facades\Redis::class,
'Request' => Illuminate\Support\Facades\Request::class,
'Response' => Illuminate\Support\Facades\Response::class,
'Route' => Illuminate\Support\Facades\Route::class,
'Schema' => Illuminate\Support\Facades\Schema::class,
'Session' => Illuminate\Support\Facades\Session::class,
'Storage' => Illuminate\Support\Facades\Storage::class,
'Str' => Illuminate\Support\Str::class,
'URL' => Illuminate\Support\Facades\URL::class,
'Validator' => Illuminate\Support\Facades\Validator::class,
'View' => Illuminate\Support\Facades\View::class,
'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class, // JWT ADDED !
'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class,
],
在网上搜索我发现了一些可能的决定,但都失败了...... 我错过了什么以及如何让它运行?
更新 #2: 经过一番搜索,我应用了下一个更改: 在我设置的后端 API 应用的 config/cors.php 中:
supportsCredentials' => true,
在 axios 请求中的 vue 端:
let config =
withCredentials:true,
headers:
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
axios.post(apiUrl + '/login', userCredentials, config)
.then((response) =>
在 app/Http/Kernel.php 中:
protected $middleware = [
...
\Barryvdh\Cors\HandleCors::class,
];
看起来 GET 请求工作正常,POST 请求不工作。
所以在我的后端 API 路由/api.php 中有 3 条路由:
Route::post('login', 'API\UserController@login', ['except' => []]);
Route::post('register', 'API\UserController@register');
Route::get('get_users_stats/id', 'API\UserController@get_users_stats');
只有最后一个工作正常。
在 config/cors.php 我有选项:
'supportsCredentials' => true,
'allowedOrigins' => ['*'],
'allowedHeaders' => ['Content-Type', 'X-Requested-With'],
'allowedMethods' => ['*'],
'exposedHeaders' => [],
'maxAge' => 0,
但如果要更改选项:
'allowedMethods' => ['POST'], // ex: ['GET', 'POST', 'PUT', 'DELETE']
那么 POST / GET DO NOT WORK 并引发 CORS 错误
另外,由于 POST 请求需要提供 csrf 令牌,这可能是问题吗?
【问题讨论】:
抱歉,不知道为什么会出错以及如何解决? 请看更新#2 对不起,没有可能的决定?是否有一些示例/演示可用于 vue/cli / Laravel 后端 REST API,使用 jwt 和 CORS 问题得到解决?上传/安装并尝试在本地运行会很有趣... 【参考方案1】:我设法通过几个附加选项修复了这个错误: 在 app/Http/Kernel.php 中:
protected $middleware = [
\Barryvdh\Cors\HandleCors::class, // MUST BE FIRST POSITION!
\App\Http\Middleware\TrustProxies::class,
...
];
在 .env 中:
ALLOWED_ORIGINS= '*' // Locally
在 config/cors.php 中:
'supportsCredentials' => true,
'allowedOrigins' => [env('ALLOWED_ORIGINS')], // '*' for local
'allowedOriginsPatterns' => [],
'allowedHeaders' => ['*'],
'allowedMethods' => ['*'],
'exposedHeaders' => [],
'maxAge' => 0,
在提供程序块中的 config/app.php 注释中:
'providers' => [
...
// Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class,
...
'aliases' => [
'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,
'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class,
在 config/jwt.php 中:
'jwt' => Tymon\JWTAuth\Providers\JWT\Namshi::class,
'auth' => Tymon\JWTAuth\Providers\Auth\Illuminate::class,
'storage' => Tymon\JWTAuth\Providers\Storage\Illuminate::class,
在 app/User.php 中:
use Tymon\JWTAuth\Contracts\JWTSubject;
...
class User extends Authenticatable implements JWTSubject
...
public function getJWTIdentifier()
return $this->getKey();
public function getJWTCustomClaims()
return [];
在客户端:
let config =
withCredentials:true, // must be false without JWT used
headers:
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
console.log('login config::')
console.log(config)
axios.post(apiUrl + '/login', userCredentials, config)
.then((response) =>
console.log('login response::')
现在检查。看来,它有效...
【讨论】:
以上是关于在安装 tymon/jwt-auth 后的 laravel Backend REST API 应用程序中再次遇到 CORS 错误的主要内容,如果未能解决你的问题,请参考以下文章
PHP Laravel 5.7 Tymon/jwt-auth 未安装
laravel composer install 无法解决 tymon/jwt-auth 的可安装包
Laravel 7.0 - tymon/jwt-auth - 检查令牌是不是有效
Laravel 8 tymon/jwt-auth 使另一个用户的令牌无效