gpt4 book ai didi

laravel - 方法 Illuminate\Auth\RequestGuard::logout 不存在 Laravel Passport

转载 作者:行者123 更新时间:2023-12-02 11:21:31 29 4
gpt4 key购买 nike

我正在使用 Laravel Passport 构建 API,我相应地删除了网络路由及其防护

如何测试用户注销?

这是我到目前为止所拥有的:

注销测试

/**
* Assert users can logout
*
* @return void
*/
public function test_logout()
{
// $data->token_type = "Bearer"
// $data->access_token = "Long string that is a valid token stripped out for brevety"
$response = $this->json('POST', '/api/logout', [], [
'Authorization' => $data->token_type . ' ' . $data->access_token
]);
$response->assertStatus(200);
}

routes/api.php

Route::post('logout', 'Auth\LoginController@logout')->name('logout');

Controller 方法使用 AuthenticatesUsers 特征,因此保留默认功能

/**
* Log the user out of the application.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function logout(Request $request)
{
$this->guard()->logout();

$request->session()->invalidate();

return $this->loggedOut($request) ?: redirect('/');
}

Error Method Illuminate\Auth\RequestGuard::logout does not exist

Laravel Documentation讨论了颁发和刷新访问 token ,但没有讨论撤销它们或执行注销

注意:我正在使用密码授予 token

注2:撤销用户的 token 不起作用

public function logout(Request $request)
{
$request->user()->token()->revoke();
return $this->loggedOut($request);
}

第二次断言测试失败

public function test_logout()
{
$response = $this->json('POST', '/api/logout', [], [
'Authorization' => $data->token_type . ' ' . $data->access_token
]);
$response->assertStatus(200); // Passes
$check_request = $this->get('/api/user');
$check_request->assertForbidden(); // Fails
}

给定需要身份验证的默认路由

Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});

Response status code [200] is not a forbidden status code.

所以这是怎么回事?如何使用 Passport 测试用户注销?

最佳答案

撤销 token 正在起作用。这是测试不起作用,但原因尚不清楚。

在一次测试中发出多个请求时,laravel 应用程序的状态不会在请求之间重置。 Auth 管理器是 Laravel 容器中的一个单例,它保留已解析的 Auth Guard 的本地缓存。已解析的身份验证守卫会保留经过身份验证的用户的本地缓存。

因此,您对 api/logout 端点的第一个请求会解析身份验证管理器,从而解析 api 防护,后者存储对您将撤销其 token 的经过身份验证的用户的引用。

现在,当您向 /api/user 发出第二个请求时,已从容器中提取已解析的身份验证管理器,已从本地缓存中提取已解析的 api 防护,并且相同已解析的用户将从守卫的本地缓存中提取。这就是第二个请求通过身份验证而不是失败的原因。

在同一测试中使用多个请求测试与身份验证相关的内容时,您需要在测试之间重置已解析的实例。此外,您不能只是取消设置已解析的身份验证管理器实例,因为当再次解析它时,它不会定义扩展的 passport 驱动程序。

因此,我发现的最简单的方法是使用反射来取消设置已解析的身份验证管理器上 protected guards 属性。您还需要在已解析的 session 防护上调用 logout 方法。

我的 TestCase 类上有一个方法,如下所示:

protected function resetAuth(array $guards = null)
{
$guards = $guards ?: array_keys(config('auth.guards'));

foreach ($guards as $guard) {
$guard = $this->app['auth']->guard($guard);

if ($guard instanceof \Illuminate\Auth\SessionGuard) {
$guard->logout();
}
}

$protectedProperty = new \ReflectionProperty($this->app['auth'], 'guards');
$protectedProperty->setAccessible(true);
$protectedProperty->setValue($this->app['auth'], []);
}

现在,您的测试将类似于:

public function test_logout()
{
$response = $this->json('POST', '/api/logout', [], [
'Authorization' => $data->token_type . ' ' . $data->access_token
]);
$response->assertStatus(200);

// Directly assert the api user's token was revoked.
$this->assertTrue($this->app['auth']->guard('api')->user()->token()->revoked);

$this->resetAuth();

// Assert using the revoked token for the next request won't work.
$response = $this->json('GET', '/api/user', [], [
'Authorization' => $data->token_type . ' ' . $data->access_token
]);
$response->assertStatus(401);
}

关于laravel - 方法 Illuminate\Auth\RequestGuard::logout 不存在 Laravel Passport,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57813795/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com