Laravel TestCase не отправляет заголовки авторизации (токен JWT)

Сводка

Мы пишем модульные тесты для проверки создания и аннулирования токенов JWT и получаем ошибку «Не удалось проанализировать токен из запроса» от JWTException каждый раз, когда мы пытаемся JWTAuth::invalidate токен.

Описание

Внутри нашего контроллера, чтобы создать токен пользователя, мы передаем адрес электронной почты пользователя, а затем возвращаем токен JWT.

После этого мы уничтожаем токен, объявляя его недействительным с помощью метода invalidateToken и пропуская токен, отправляя заголовок авторизации.

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.

Когда мы пытаемся написать тест для этого метода, мы сталкиваемся с ответом об ошибке и сообщением об ошибке «Токен не может быть проанализирован из запроса».

Наш тест выглядит следующим образом:

public function testInvalidateToken()
{
    $createUserToken = $this->call('POST', '/token/create', ['email' => '[email protected]']);
    $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

PHPUnit 3.7.28

* РЕДАКТИРОВАТЬ * Обновлено до PHPUnit 4.7.6, и по-прежнему не удается отправить заголовок авторизации.

* РЕШЕНИЕ *
В моем методе __construct контроллера у меня есть эти несколько строк кода, которые выполняются и решают мою проблему.

if ((\App::environment() == 'testing') && array_key_exists("HTTP_Authorization",  Request::server())) {
    JWTAuth::setRequest(\Route::getCurrentRequest());
}

person gvhuyssteen    schedule 09.07.2015    source источник


Ответы (4)


Мы столкнулись с похожей проблемой при написании тестов на 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"];
        }
person Emilio Borraz    schedule 14.07.2015

Я попробовал следующий код в конструкторе контроллера:

if (env('APP_ENV') == 'testing' 
        && array_key_exists("HTTP_AUTHORIZATION", request()->server())) {
    JWTAuth::setRequest(\Route::getCurrentRequest());
} 
person John Huang    schedule 04.10.2015
comment
Я пробую ваш код, но \Route::getCurrentRequest() возвращает null. Любая идея, почему это может быть? спасибо - person Munteanu Sergiu; 07.01.2017

Есть два способа отправить токен в наш API. Если заголовок не работает, просто добавьте его к своему URL-адресу. Пример:

 http://api.mysite.com/me?token={yourtokenhere}

Итак, вы можете сделать это:

В вашем тестовом примере

public function signIn($data=['email'=>'[email protected]', '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);
 }
person Emeka Mbah    schedule 10.11.2015

Apache по умолчанию использует этот заголовок. Вы можете исправить поведение Apache, добавив это в файл .conf вашего сайта:

# Workaround apache consuming the header.
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
person Antony Penn    schedule 15.02.2019