ฉันได้รับข้อผิดพลาดนี้จาก Laravel Sanctum ฉันแก้ไขโดยเพิ่ม\Illuminate\Session\Middleware\StartSession::class,
ไปยังapi
กลุ่มมิดเดิลแวร์ใน Kernel.php แต่ภายหลังฉันพบว่า "ใช้งานได้" เนื่องจากมีการเพิ่มเส้นทางการตรวจสอบสิทธิ์ของฉันapi.php
แทนweb.php
ดังนั้น Laravel จึงใช้ตัวป้องกันการตรวจสอบสิทธิ์ที่ไม่ถูกต้อง
ฉันย้ายเส้นทางเหล่านี้มาที่นี่web.php
แล้วพวกเขาก็เริ่มทำงานอย่างถูกต้องกับAuthenticatesUsers.php
ลักษณะ:
Route::group(['middleware' => ['guest', 'throttle:10,5']], function () {
Route::post('register', 'Auth\RegisterController@register')->name('register');
Route::post('login', 'Auth\LoginController@login')->name('login');
Route::post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail');
Route::post('password/reset', 'Auth\ResetPasswordController@reset');
Route::post('email/verify/{user}', 'Auth\VerificationController@verify')->name('verification.verify');
Route::post('email/resend', 'Auth\VerificationController@resend');
Route::post('oauth/{driver}', 'Auth\OAuthController@redirectToProvider')->name('oauth.redirect');
Route::get('oauth/{driver}/callback', 'Auth\OAuthController@handleProviderCallback')->name('oauth.callback');
});
Route::post('logout', 'Auth\LoginController@logout')->name('logout');
ฉันพบปัญหาหลังจากได้รับข้อผิดพลาดแปลก ๆ อีกอย่างเกี่ยวกับRequestGuard::logout()
ไม่มีอยู่จริง
มันทำให้ฉันรู้ว่าเส้นทางการตรวจสอบสิทธิ์ที่กำหนดเองของฉันกำลังเรียกใช้เมธอดจากลักษณะ AuthenticatesUsers แต่ฉันไม่ได้ใช้Auth::routes()
เพื่อทำมันให้สำเร็จ แล้วฉันตระหนัก Laravel routes/web.php
ใช้ยามเว็บโดยการเริ่มต้นและการที่เส้นทางหมายถึงควรจะอยู่ใน
นี่คือลักษณะการตั้งค่าของฉันในขณะนี้ด้วย Sanctum และแอป Vue SPA ที่แยกออกจากกัน:
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' => [
EnsureFrontendRequestsAreStateful::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
'throttle:60,1',
],
];
หมายเหตุ:ด้วย Laravel Sanctum และ Vue SPA โดเมนเดียวกันคุณจะใช้ httpOnly cookies สำหรับคุกกี้เซสชันและจดจำคุกกี้ของฉันและคุกกี้ที่ไม่ปลอดภัยสำหรับ CSRF ดังนั้นคุณควรใช้การweb
ป้องกันเพื่อรับรองความถูกต้องและทุก ๆ เส้นทางที่ได้รับการป้องกันอื่น ๆ ควรใช้เส้นทางการส่งคืน JSON auth:sanctum
มิดเดิลแวร์
config / auth.php
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
...
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
],
แล้วคุณสามารถมีการทดสอบหน่วยเช่นนี้ซึ่งวิกฤตAuth::check()
, Auth::user()
และAuth::logout()
การทำงานเป็นไปตามคาดกับการกำหนดค่าที่น้อยที่สุดและการใช้งานสูงสุดAuthenticatesUsers
และRegistersUsers
ลักษณะ
นี่คือการทดสอบหน่วยการเข้าสู่ระบบของฉันสองสามรายการ:
TestCase.php
/**
* Creates and/or returns the designated regular user for unit testing
*
* @return \App\User
*/
public function user() : User
{
$user = User::query()->firstWhere('email', 'test-user@example.com');
if ($user) {
return $user;
}
// User::generate() is just a wrapper around User::create()
$user = User::generate('Test User', 'test-user@example.com', self::AUTH_PASSWORD);
return $user;
}
/**
* Resets AuthManager state by logging out the user from all auth guards.
* This is used between unit tests to wipe cached auth state.
*
* @param array $guards
* @return void
*/
protected function resetAuth(array $guards = null) : void
{
$guards = $guards ?: array_keys(config('auth.guards'));
foreach ($guards as $guard) {
$guard = $this->app['auth']->guard($guard);
if ($guard instanceof SessionGuard) {
$guard->logout();
}
}
$protectedProperty = new \ReflectionProperty($this->app['auth'], 'guards');
$protectedProperty->setAccessible(true);
$protectedProperty->setValue($this->app['auth'], []);
}
LoginTest.php
protected $auth_guard = 'web';
/** @test */
public function it_can_login()
{
$user = $this->user();
$this->postJson(route('login'), ['email' => $user->email, 'password' => TestCase::AUTH_PASSWORD])
->assertStatus(200)
->assertJsonStructure([
'user' => [
...expectedUserFields,
],
]);
$this->assertEquals(Auth::check(), true);
$this->assertEquals(Auth::user()->email, $user->email);
$this->assertAuthenticated($this->auth_guard);
$this->assertAuthenticatedAs($user, $this->auth_guard);
$this->resetAuth();
}
/** @test */
public function it_can_logout()
{
$this->actingAs($this->user())
->postJson(route('logout'))
->assertStatus(204);
$this->assertGuest($this->auth_guard);
$this->resetAuth();
}
ฉันลบล้างregistered
และauthenticated
วิธีการในลักษณะการตรวจสอบสิทธิ์ Laravel เพื่อให้พวกเขาส่งคืนวัตถุผู้ใช้แทนที่จะเป็นเพียง 204 ตัวเลือก:
public function authenticated(Request $request, User $user)
{
return response()->json([
'user' => $user,
]);
}
protected function registered(Request $request, User $user)
{
return response()->json([
'user' => $user,
]);
}
ดูรหัสผู้ขายสำหรับลักษณะการตรวจสอบสิทธิ์ คุณสามารถใช้โดยไม่แตะต้องรวมทั้งสองวิธีข้างต้น
- ผู้ขาย / laravel / ui / auth-backend / RegistersUsers.php
- ผู้ขาย / laravel / ui / auth-backend / AuthenticatesUsers.php
นี่คือการดำเนินการ Vuex ของ Vue SPA สำหรับการเข้าสู่ระบบ:
async login({ commit }, credentials) {
try {
const { data } = await axios.post(route('login'), {
...credentials,
remember: credentials.remember || undefined,
});
commit(FETCH_USER_SUCCESS, { user: data.user });
commit(LOGIN);
return commit(CLEAR_INTENDED_URL);
} catch (err) {
commit(LOGOUT);
throw new Error(`auth/login# Problem logging user in: ${err}.`);
}
},
async logout({ commit }) {
try {
await axios.post(route('logout'));
return commit(LOGOUT);
} catch (err) {
commit(LOGOUT);
throw new Error(`auth/logout# Problem logging user out: ${err}.`);
}
},
ฉันใช้เวลากว่าหนึ่งสัปดาห์ในการรับ Laravel Sanctum + การทดสอบหน่วย Vue SPA + โดเมนเดียวกันทั้งหมดทำงานได้ตามมาตรฐานของฉันดังนั้นหวังว่าคำตอบของฉันที่นี่จะช่วยประหยัดเวลาของผู้อื่นในอนาคต