9

我正在尝试使用 Codeception 测试我的 Laravel 4 REST API,但是当我尝试通过我的 Authorization 标头(使用 REST 模块的 $I->amBearerAuthenticated() 函数)发送时,它并没有通过最终请求。

据我所见,Symfony2 BrowserKit 模块修改了任何添加到 HTTP_XXX_XXX 格式的标头,因此发送的标头似乎是 HTTP_AUTHORIZATION - 但是,当我在我的应用程序中输出接收到的标头时,授权和 HTTP_AUTHORIZATION 都不存在。

如果有帮助,这是我的 Codeception 测试:

public function loginAndHitProtectedPage(ApiTester $I)
{
    $I->wantTo('login and successfully get to a protected page');
    $I->sendPOST('/auth/login', ['username' => 'user1', 'password' => 'pass']);
    $I->seeResponseIsJson();
    $token = $I->grabDataFromJsonResponse('token');
    $I->amBearerAuthenticated($token);
    $I->sendGET('/runs');
    $I->seeResponseCodeIs(200);
    $I->seeResponseIsJson();
    $I->dontSeeResponseContains('error');
}

根据 BrowserKit 发送的标头($this->client->getInternalRequest()->getServer()在 REST 模块中的输出):

HTTP_HOST   :   localhost
HTTP_USER_AGENT :   Symfony2 BrowserKit
HTTP_AUTHORIZATION  :   Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9sb2NhbGhvc3RcL2F1dGhcL2xvZ2luIiwic3ViIjoxLCJpYXQiOjE0MjE3ODY0NDEsImV4cCI6MTQyMTg3Mjg0MX0.XxxxZMe8gwF9GS8CdKsh5coNQer1c6G6prK05QJEmDQ     
HTTP_REFERER    :   http://localhost/auth/login 
HTTPS   :   false

根据 PHP 接收的标头:

Accept:          text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset:  ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Language: en-us,en;q=0.5
Content-Type:    application/x-www-form-urlencoded
Host:            localhost
Referer:         http://localhost/auth/login
User-Agent:      Symfony2 BrowserKit

令牌被正确接收,但我的 API(正确)在 GET 请求上返回 401,因为它没有收到令牌。

任何帮助将不胜感激!

4

3 回答 3

4

我正在使用 Laravel 5(与 L4 没有太大区别)和 REST 模块。这就是我现在正在做的方式:

protected $token;
public function _before(ApiTester $I)
{
    $user = TestDummy(...);
    $I->sendPOST('/v1/auth/login', [
      'email' => $user->email, 
      'password' => $user->password
    ]);
    $this->token = $I->grabDataFromResponseByJsonPath('$.token');
}

然后在我的测试中:

// Do stuff ...
$I->amBearerAuthenticated($this->token[0]);
// Do more stuff ...

我确信有更好的方法可以做到这一点,但在我找到更好的方法之前,这是可行的。

于 2015-01-21T19:05:34.547 回答
4

有一种解决方法。使用$I->amHttpAuthenticated("test", "test")使Authorization:标题永久化。不确定这是错误还是功能。而是手动构建Authorization: Basic标题,以便您可以在设置标题之前将其删除Authorization: Bearer

$I = new ApiTester($scenario);
$I->wantTo("fetch token and use it as bearer");

/* This does not work. */
/* $I->amHttpAuthenticated("test", "test"); */

/* Instead use this. */
$I->setHeader("Authorization", "Basic dGVzdDp0ZXN0");

$I->haveHttpHeader("Content-Type", "application/json");    
$I->sendPOST("token", ["read", "write"]);
$I->seeResponseCodeIs(201);
$I->seeResponseIsJson();
$I->seeResponseContainsJson(["status" => "ok"]);

$token = $I->grabDataFromJsonResponse("token");

/* Delete the basic auth header before adding bearer. */
$I->deleteHeader("Authorization");
$I->amBearerAuthenticated($token);
于 2015-04-16T10:24:10.460 回答
2

在深入研究了 Laravel 和 Codeception 的内容之后,我发现问题在于我同时使用 Laravel4 模块和 REST 模块这一事实。我没有意识到将 Laravel4 用于 HTTP 请求实际上只是在同一会话中模拟对路由的请求,因此我的 JWTAuth 对象仅在任何特定测试中的第一次 REST 调用时才从 IOC 容器中解析出来。这意味着在进行后续调用时,第一次调用的请求(包括标头)被保留,因此看不到 Authorization 标头(此时正通过 Request 对象正确传递)。

我实际上只是使用 Laravel4 模块将我的环境设置为“测试”并确保我的过滤器在该环境中运行,所以我现在只需要找出一种不同的方法来设置它,而无需修改我的引导程序/ start.php 每次我想运行我的测试。

于 2015-01-21T16:35:57.223 回答