Sal*_*301 10 phpunit oauth-2.0 laravel laravel-passport
正在Laravel Passport 用于构建 API,我相应地删除了网络路由及其防护
如何测试用户注销?
这是我到目前为止:
Logout Test
/**
* 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);
}
Run Code Online (Sandbox Code Playgroud)
routes/api.php
Route::post('logout', 'Auth\LoginController@logout')->name('logout');
Run Code Online (Sandbox Code Playgroud)
控制器方法使用AuthenticatesUserstrait,因此保留默认功能
/**
* 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('/');
}
Run Code Online (Sandbox Code Playgroud)
错误方法 Illuminate\Auth\RequestGuard::logout 不存在
该Laravel文档关于发布和刷新访问令牌,但没有关于撤销他们或进行注销会谈
public function logout(Request $request)
{
$request->user()->token()->revoke();
return $this->loggedOut($request);
}
Run Code Online (Sandbox Code Playgroud)
Test Fails on second assertion
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
}
Run Code Online (Sandbox Code Playgroud)
鉴于需要身份验证的默认路由
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Run Code Online (Sandbox Code Playgroud)
响应状态代码 [200] 不是禁止状态代码。
发生什么了?以及如何使用 Passport 测试用户注销?
提前致谢
Daz*_*zle 19
auth()->guard('web')->logout()
pat*_*cus 11
撤销令牌正在起作用。是测试不起作用,但不清楚为什么。
在一次测试中发出多个请求时,laravel 应用程序的状态不会在请求之间重置。Auth 管理器是 laravel 容器中的一个单例,它保存已解析的 auth 守卫的本地缓存。已解析的 auth 守卫保留了已认证用户的本地缓存。
因此,您对api/logout端点的第一个请求将解析身份验证管理器,该管理器解析 API 防护,该防护存储对您将撤销其令牌的已认证用户的引用。
现在,当您向 发出第二个请求时/api/user,已解析的身份验证管理器将从容器中拉出,已解析的 api 防护从其本地缓存中拉出,并且同一个已解析的用户从防护的本地缓存中拉出。这就是第二个请求通过身份验证而不是失败的原因。
在同一个测试中使用多个请求测试与身份验证相关的内容时,您需要在测试之间重置已解析的实例。此外,您不能只是取消设置已解析的身份验证管理器实例,因为再次解析时,它不会passport定义扩展驱动程序。
所以,我发现的最简单的方法是使用反射来取消设置guards已解析身份验证管理器上的受保护属性。您还需要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'], []);
}
Run Code Online (Sandbox Code Playgroud)
现在,您的测试将类似于:
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);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7337 次 |
| 最近记录: |