Laravel 始终通过 CreateFreshApiToken 进行护照身份验证 returns {"message":"Unauthenticated."}
Laravel passport auth through CreateFreshApiToken always returns {"message":"Unauthenticated."}
我试图让我的用户在登录后通过 Javasscript 使用我自己的 API,如 https://laravel.com/docs/5.7/passport#consuming-your-api-with-javascript
所述
我已经安装了 Passport。我的网络中间件定义为
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Barryvdh\Cors\HandleCors::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\SetLocale::class,
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
我看到 "laravel_token" cookie 似乎确实是在登录后创建的。
然后我尝试向 API 路由发送一个简单的获取请求
window.$.ajax({
headers: {
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
type: 'GET',
url: 'https://mywebsite.test/api/testApi',
success: function (response) {
console.log(response);
},
error: function (xhr) {
console.error(xhr.responseText);
}
});
我设法得到的唯一回应是
{"message":"Unauthenticated."}
我能错过什么?
更新
请求是从子域 client.mywebsite.test 执行的,经过调查,这似乎就是问题所在。当从 mywebsite.test 执行 ajax 调用时,身份验证效果很好。我该如何为子域修复该问题?
从子域请求时请求 headers:
OPTIONS /api/testApi HTTP/1.1
Host: mywebsite.test
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: https://client.mywebsite.test
Access-Control-Request-Headers: x-csrf-token,x-requested-with
Accept: */*
Referer: https://client.mywebsite.test/home
从域请求时请求 headers:
GET /api/testApi HTTP/1.1
Host: mywebsite.test
Connection: keep-alive
X-CSRF-TOKEN: fLTkaq9p62FROutzch2iE9IF864al8adFnxptbve
X-Requested-With: XMLHttpRequest
Cookie: laravel_token=[...]; XSRF-TOKEN=[...]; mywebsite_session=[...];
这在 Laravel 5.6 项目中对我有用:
<?php
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
class EncryptCookies extends Middleware
{
/**
* The names of the cookies that should not be encrypted.
*
* @var array
*/
protected static $serialize = true;
/**
* The names of the cookies that should not be encrypted.
*
* @var array
*/
protected $except = [
//
];
}
在 EncryptCookies
中间件上将 属性 $serialize
设置为 true
。
来源:https://laravel.com/docs/5.6/upgrade#upgrade-5.6.30
来源:
浏览浏览浏览后..
事实证明问题确实来自于 cookie 没有随 CORS 请求一起发送。我通过将 "withCredentials" 添加到我的 Ajax 调用来修复它:
window.$.ajax({
headers: {
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
xhrFields: {
withCredentials: true
},
type: 'GET',
url: 'https://mywebsite.test/api/testApi',
success: function (response) {
console.log(response);
},
error: function (xhr) {
console.error(xhr.responseText);
}
});
您还需要确保 headers 您的回复指定接受凭据:
header('Access-Control-Allow-Credentials: true');
我试图让我的用户在登录后通过 Javasscript 使用我自己的 API,如 https://laravel.com/docs/5.7/passport#consuming-your-api-with-javascript
所述我已经安装了 Passport。我的网络中间件定义为
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Barryvdh\Cors\HandleCors::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\SetLocale::class,
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
我看到 "laravel_token" cookie 似乎确实是在登录后创建的。
然后我尝试向 API 路由发送一个简单的获取请求
window.$.ajax({
headers: {
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
type: 'GET',
url: 'https://mywebsite.test/api/testApi',
success: function (response) {
console.log(response);
},
error: function (xhr) {
console.error(xhr.responseText);
}
});
我设法得到的唯一回应是
{"message":"Unauthenticated."}
我能错过什么?
更新
请求是从子域 client.mywebsite.test 执行的,经过调查,这似乎就是问题所在。当从 mywebsite.test 执行 ajax 调用时,身份验证效果很好。我该如何为子域修复该问题?
从子域请求时请求 headers:
OPTIONS /api/testApi HTTP/1.1
Host: mywebsite.test
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: https://client.mywebsite.test
Access-Control-Request-Headers: x-csrf-token,x-requested-with
Accept: */*
Referer: https://client.mywebsite.test/home
从域请求时请求 headers:
GET /api/testApi HTTP/1.1
Host: mywebsite.test
Connection: keep-alive
X-CSRF-TOKEN: fLTkaq9p62FROutzch2iE9IF864al8adFnxptbve
X-Requested-With: XMLHttpRequest
Cookie: laravel_token=[...]; XSRF-TOKEN=[...]; mywebsite_session=[...];
这在 Laravel 5.6 项目中对我有用:
<?php
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
class EncryptCookies extends Middleware
{
/**
* The names of the cookies that should not be encrypted.
*
* @var array
*/
protected static $serialize = true;
/**
* The names of the cookies that should not be encrypted.
*
* @var array
*/
protected $except = [
//
];
}
在 EncryptCookies
中间件上将 属性 $serialize
设置为 true
。
来源:https://laravel.com/docs/5.6/upgrade#upgrade-5.6.30
来源:
浏览浏览浏览后..
事实证明问题确实来自于 cookie 没有随 CORS 请求一起发送。我通过将 "withCredentials" 添加到我的 Ajax 调用来修复它:
window.$.ajax({
headers: {
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
xhrFields: {
withCredentials: true
},
type: 'GET',
url: 'https://mywebsite.test/api/testApi',
success: function (response) {
console.log(response);
},
error: function (xhr) {
console.error(xhr.responseText);
}
});
您还需要确保 headers 您的回复指定接受凭据:
header('Access-Control-Allow-Credentials: true');