我正在为 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 库编写自定义逻辑。
auth()->forgetGuards();
但对于智威汤逊,你可能还需要额外做:
app('tymon.jwt')->unsetToken();
或者
app()->instance('tymon.jwt', null);
由于
->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 部分相同的操作。
对于
jwt-auth
,您可以这样做来清除auth用户:
auth()->forgetGuards();
app()->instance('tymon.jwt', null);
第一行,丢弃现有的缓存防护。第二,确保重新创建防护时,它不会重用相同的底层 jwt 实例。
好问题。我也曾为此苦苦挣扎。昨天我对这个主题进行了深入研究。事实证明,TokenGuard 存在实现问题,因为加载新请求后,经过身份验证的用户不会刷新。为了解决这个问题,需要以下内容:
(1) 对于 Laravel >9.x 上非常具体的测试,您可以使用:
$this->refreshApplication();
这会重置每个请求之间的应用程序状态,确保调用之间不会保留任何数据或标头。
(2) 但是,如果可能的话,最好将请求拆分为单独的重点测试。这种方法可以让您的测试套件更干净、更易于维护。