如何在测试中的 API 调用之间重置 Laravel AuthManager/guards?

问题描述 投票:0回答:4

我正在为 API 编写功能测试,我想测试自定义身份验证逻辑。

我知道当我调用登录 API 端点时,Laravel 会缓存用户已登录的事实,因此测试中的下一个 API 调用会认为用户已经通过身份验证...

因此,对于一个测试,如何禁用 Laravel 身份验证缓存魔法,以便我可以手动提供 Bearer 身份验证令牌来检查我的自定义身份验证逻辑是否有效?

我正在考虑清除 AuthManager 中的守卫,或者完全清除 AuthManager,这样 Laravel 将被迫重新初始化它。但我没有运气弄清楚如何以有效的方式做到这一点。

这是一些伪示例代码:

public function testLogin()
{
    $responseData = $this->post('/login', ['email' => $this->user->email, 'password' => 'password'])->json();

    $this->get('/endpoint-requiring-auth')->assertOk();

    //
    // $this->logicToResetAuth() ?
    //

    $this->get('/endpoint-requiring-auth')->assertUnauthorized();
    
    // I want to manually have to pass the token to get it to work now.
    $this->get('/endpoint-requiring-auth', ['Authorization' => "Bearer $responseData[access_token]"])
        ->assertOk();
}

此外,未知的重置逻辑应该会影响多个防护装置。

哦,是的,我正在围绕 JWT-Auth 库编写自定义逻辑。

php laravel testing jwt
4个回答
6
投票

对于 Laravel 8.x (也许更新)

auth()->forgetGuards();

但对于智威汤逊,你可能还需要额外做:

app('tymon.jwt')->unsetToken();

或者

app()->instance('tymon.jwt', null);

对于 Laravel 7.x (可能更旧)

由于

->forgetGuards()
在此版本中尚未发明,并且
guards
数组是
protected
,请执行以下操作:

/** @var \Illuminate\Auth\AuthManager $auth */
$auth = app('auth');
$mirror = new \ReflectionObject( $auth );
$prop = $mirror->getProperty( 'guards' );
$prop->setAccessible(true);
$prop->setValue($auth, []);
$prop->setAccessible(false); // Back to protected.

但是对于 JWT,请执行与上述 Laravel 8 部分相同的操作。


2
投票

对于

jwt-auth
,您可以这样做来清除auth用户:

auth()->forgetGuards();
app()->instance('tymon.jwt', null);

第一行,丢弃现有的缓存防护。第二,确保重新创建防护时,它不会重用相同的底层 jwt 实例。


0
投票

好问题。我也曾为此苦苦挣扎。昨天我对这个主题进行了深入研究。事实证明,TokenGuard 存在实现问题,因为加载新请求后,经过身份验证的用户不会刷新。为了解决这个问题,需要以下内容:

  1. 将 TokenGuard 类扩展为您自己的类并重载方法 setRequest。添加 '$this->user = null;'在通过 'returnparent::setRequest($request);' 调用父实现之前
  2. 使用 Auth::extend 才能使用您的自定义 TokenGuard
  3. 此后,每个新请求都会自动重置经过身份验证的用户

另请参阅 https://code.tutsplus.com/tutorials/how-to-create-a-custom-authentication-guard-in-laravel--cms-29667


0
投票

(1) 对于 Laravel >9.x 上非常具体的测试,您可以使用:

$this->refreshApplication();

这会重置每个请求之间的应用程序状态,确保调用之间不会保留任何数据或标头。

(2) 但是,如果可能的话,最好将请求拆分为单独的重点测试。这种方法可以让您的测试套件更干净、更易于维护。

© www.soinside.com 2019 - 2024. All rights reserved.