Laravel Passport注销/撤销令牌的单元测试



我正在使用Laravel Passport,并在控制器中具有注销功能。见下文:

public function logout(Request $request){
auth()->user()->token()->revoke();
$response = ['message' => 'You have been successfully logged out!'];
return response($response, 200);
}

我现在正试图为此编写一个单元测试,但即使在注销和令牌被撤销后,用户仍然登录。我发现这个方法IlluminateAuthRequestGuard::logout不存在Laravel Passport,但即使是这个解决方案也不适合我。我猜这可能是因为我使用的是Laravel 8。我的单元测试看起来像这样:

public function testLogout()
{
//Random email and password
$email = $this->faker->email;
$password = $this->faker->password(8);
//Create a user
$this->createUser($this->faker->name, $email, $password);
//Data for the post request
$data = [
'email' => $email,
'password' => $password
];
//Try login
$response = $this->json('POST','api/login', $data);
//Assert it was successful
$response->assertStatus(200);
//Assert we received a token
$this->assertArrayHasKey('token', $response->json());
//Get the token
$token = $response->json()['token'];
//Setup authenticated header
$header = [
'Authorization' => 'Bearer '.$token
];
//try to access authenticated route
$response = $this->json('get', 'api/ads', [], $header);
//Assert it was successful
$response->assertStatus(200);
$this->resetAuth();
//Logout the user
$response = $this->post('api/logout', [], $header);
//Assert it was successful
$response->assertStatus(200);
//try to access authenticated route
$response = $this->json('get', 'api/ads', [], $header);
//Assert it returns unathorized error
$response->assertStatus(401);

//Delete the user
User::where('email', $email)->delete();
}

结果如下:

期望状态码401,但接收到200。断言401与200相同失败。

你在一次测试中做得太多了。但除此之外,我无法发现代码中的任何问题。但这对我来说很有效:

class LogoutController extends Controller
{
public function __construct()
{
$this->middleware('auth:api');
}
public function logout()
{
Auth::user()->token()->revoke();
$tokenId = Auth::user()->token()->id;
$refreshTokenRepository = app('LaravelPassportRefreshTokenRepository');
$refreshTokenRepository->revokeRefreshTokensByAccessTokenId($tokenId);
return response(null, Response::HTTP_NO_CONTENT);
}
}

测试可以简单地做如下的事情:

public function testAnAuthenticatedUserCanLogout()
{
$user = User::factory()->create();
Passport::actingAs($user);
$this->postJson('/api/logout')
->assertNoContent();
}

您的logout方法看起来很奇怪。我会这样做

use IlluminateSupportFacadesAuth;
// ... other controller methods
public function logout(Request $request)
{
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
// ...do a redirect or other stuff
}

退出。这应该可以正确地注销用户。这也是Laravel文档中建议的方法。

要从Laravel Passport注销,可以运行

if (Auth::check()) {
Auth::user()->token()->revoke();
}

撤销当前使用的令牌。这肯定会将用户从他请求注销的当前设备注销。

确保在您的routes/web.php中您的logout路由位于group(['middleware' => 'auth:api']组内。

如果您想从他登录的所有设备注销,您也可以从数据库中删除令牌。

最新更新