Laravel TestCase 未发送授权 headers(JWT 令牌)
Laravel TestCase not sending Authorization headers (JWT Token)
总结
我们正在编写单元测试来测试 JWT 令牌的创建和失效,并且每次我们尝试 JWTAuth::invalidate 令牌时都会收到来自 JWTException 的 "The token could not be parsed from the request" 错误。
描述
在我们的控制器中,为了创建用户令牌,我们传递用户电子邮件地址,然后返回 JWT 令牌。
之后,我们通过使用 invalidateToken 方法使令牌无效并通过发送授权来传递令牌来销毁令牌 header。
public function invalidateToken()
{
try {
JWTAuth::invalidate(JWTAuth::getToken());
return Response::json(['status' => 'success'], 200);
} catch (JWTException $e) {
return Response::json(['status' => 'error', 'message' => $e->getMessage()], 401);
}
}
这通过使用 Postman 和 PHPStorms Restful 客户端完美地工作。
当我们尝试为此方法编写测试时,我们面临错误响应和 "The token could not be parsed from the request" 错误消息。
我们的测试如下:
public function testInvalidateToken()
{
$createUserToken = $this->call('POST', '/token/create', ['email' => 'test@test.com']);
$user = $this->parseJson($createUserToken);
$response = $this->call('POST', '/token/invalidate',
[/* params */], [/* cookies */], [/* files */], ['HTTP_Authorization' => 'Bearer '.$user->token]);
// var_dump($user->token);
// die();
$data = $this->parseJson($response);
$this->assertEquals($data->status, 'success');
$this->assertEquals($data->status, '200');
}
我们正在使用 Laravel 5.1(在服务器参数之前将 cookie 作为参数)
PHP 版本 5.6.10
PHP单元 3.7.28
* 编辑 *
已更新至 PHPUnit 4.7.6,但仍无法通过授权发送 header。
* 解决方案 *
在我的控制器 __construct 方法中,我有这几行代码 运行 并解决了我的问题。
if ((\App::environment() == 'testing') && array_key_exists("HTTP_Authorization", Request::server())) {
JWTAuth::setRequest(\Route::getCurrentRequest());
}
我们在 Laravel 4.2 上编写测试时遇到了类似的问题,但我们在 运行 测试环境中的应用程序时添加了以下行:
// This will only work when unit testing
if ((\App::environment() == 'testing') && array_key_exists("HTTP_Authorization", LRequest::server())) {
$headers['Authorization'] = LRequest::server()["HTTP_Authorization"];
}
我在控制器构造函数中尝试了以下代码:
if (env('APP_ENV') == 'testing'
&& array_key_exists("HTTP_AUTHORIZATION", request()->server())) {
JWTAuth::setRequest(\Route::getCurrentRequest());
}
有两种方法可以将令牌发送到我们的 API,如果 header 不起作用,只需附加到您的 URL。
示例:
http://api.mysite.com/me?token={yourtokenhere}
所以你可以这样做:
在你的测试用例中
public function signIn($data=['email'=>'youremail@yahoo.com', 'password'=>'password'])
{
$this->post('/auth/signin', $data);
$content = json_decode($this->response->getContent());
$this->assertObjectHasAttribute('token', $content, 'Token does not exists');
$this->token = $content->token;
return $this;
}
这将获取令牌并将其存储在 $this->token 中,以便您可以使用它来发出请求
然后在稍后的测试中
public function testResticted()
{
$this->signIn();
$this->call('GET', '/restricted/page', ['token'=>$this->token], $cookies = [], $files = [], $server = []);
dump($this->response);
}
Apache 默认使用这个 header。您可以通过将此添加到您的站点 .conf 文件来修复 apache 行为:
# Workaround apache consuming the header.
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
总结
我们正在编写单元测试来测试 JWT 令牌的创建和失效,并且每次我们尝试 JWTAuth::invalidate 令牌时都会收到来自 JWTException 的 "The token could not be parsed from the request" 错误。
描述
在我们的控制器中,为了创建用户令牌,我们传递用户电子邮件地址,然后返回 JWT 令牌。
之后,我们通过使用 invalidateToken 方法使令牌无效并通过发送授权来传递令牌来销毁令牌 header。
public function invalidateToken()
{
try {
JWTAuth::invalidate(JWTAuth::getToken());
return Response::json(['status' => 'success'], 200);
} catch (JWTException $e) {
return Response::json(['status' => 'error', 'message' => $e->getMessage()], 401);
}
}
这通过使用 Postman 和 PHPStorms Restful 客户端完美地工作。
当我们尝试为此方法编写测试时,我们面临错误响应和 "The token could not be parsed from the request" 错误消息。
我们的测试如下:
public function testInvalidateToken()
{
$createUserToken = $this->call('POST', '/token/create', ['email' => 'test@test.com']);
$user = $this->parseJson($createUserToken);
$response = $this->call('POST', '/token/invalidate',
[/* params */], [/* cookies */], [/* files */], ['HTTP_Authorization' => 'Bearer '.$user->token]);
// var_dump($user->token);
// die();
$data = $this->parseJson($response);
$this->assertEquals($data->status, 'success');
$this->assertEquals($data->status, '200');
}
我们正在使用 Laravel 5.1(在服务器参数之前将 cookie 作为参数)
PHP 版本 5.6.10
PHP单元 3.7.28
* 编辑 * 已更新至 PHPUnit 4.7.6,但仍无法通过授权发送 header。
* 解决方案 *
在我的控制器 __construct 方法中,我有这几行代码 运行 并解决了我的问题。
if ((\App::environment() == 'testing') && array_key_exists("HTTP_Authorization", Request::server())) {
JWTAuth::setRequest(\Route::getCurrentRequest());
}
我们在 Laravel 4.2 上编写测试时遇到了类似的问题,但我们在 运行 测试环境中的应用程序时添加了以下行:
// This will only work when unit testing
if ((\App::environment() == 'testing') && array_key_exists("HTTP_Authorization", LRequest::server())) {
$headers['Authorization'] = LRequest::server()["HTTP_Authorization"];
}
我在控制器构造函数中尝试了以下代码:
if (env('APP_ENV') == 'testing'
&& array_key_exists("HTTP_AUTHORIZATION", request()->server())) {
JWTAuth::setRequest(\Route::getCurrentRequest());
}
有两种方法可以将令牌发送到我们的 API,如果 header 不起作用,只需附加到您的 URL。 示例:
http://api.mysite.com/me?token={yourtokenhere}
所以你可以这样做:
在你的测试用例中
public function signIn($data=['email'=>'youremail@yahoo.com', 'password'=>'password'])
{
$this->post('/auth/signin', $data);
$content = json_decode($this->response->getContent());
$this->assertObjectHasAttribute('token', $content, 'Token does not exists');
$this->token = $content->token;
return $this;
}
这将获取令牌并将其存储在 $this->token 中,以便您可以使用它来发出请求
然后在稍后的测试中
public function testResticted()
{
$this->signIn();
$this->call('GET', '/restricted/page', ['token'=>$this->token], $cookies = [], $files = [], $server = []);
dump($this->response);
}
Apache 默认使用这个 header。您可以通过将此添加到您的站点 .conf 文件来修复 apache 行为:
# Workaround apache consuming the header.
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]