【问题标题】:Laravel TestCase not sending Authorization headers (JWT Token)Laravel TestCase 未发送授权标头(JWT 令牌)
【发布时间】:2015-09-27 08:00:08
【问题描述】:

总结

我们正在编写单元测试来测试 JWT 令牌的创建和失效,并且每次我们尝试 JWTAuth::invalidate 令牌时都会从 JWTException 返回“无法从请求中解析令牌”错误。

说明

在我们的控制器内部,为了创建用户令牌,我们传递用户电子邮件地址,然后返回 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' => '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

PHPUnit 3.7.28

* 编辑 * 更新到 PHPUnit 4.7.6 仍然无法通过 Authorization 标头发送。

* 解决方案 *
在我的控制器 __construct 方法中,我有这几行代码正在运行并解决了我的问题。

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

【问题讨论】:

    标签: php phpunit laravel-5 testcase


    【解决方案1】:

    我们在 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"];
            }
    

    【讨论】:

      【解决方案2】:

      我在 Controller 构造函数中尝试了以下代码:

      if (env('APP_ENV') == 'testing' 
              && array_key_exists("HTTP_AUTHORIZATION", request()->server())) {
          JWTAuth::setRequest(\Route::getCurrentRequest());
      } 
      

      【讨论】:

      • 我正在尝试您的代码,但 \Route::getCurrentRequest() 返回 null。知道为什么会这样吗?谢谢
      【解决方案3】:

      有两种方法可以将令牌发送到我们的 API,如果标头不起作用,只需附加到您的 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);
       }
      

      【讨论】:

        【解决方案4】:

        Apache 默认使用此标头。您可以通过将其添加到您的站点 .conf 文件来修复 apache 行为:

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

        【讨论】:

          猜你喜欢
          • 2019-02-27
          • 1970-01-01
          • 2016-03-08
          • 2019-10-17
          • 1970-01-01
          • 2015-09-19
          • 2015-04-25
          • 2023-02-23
          • 2021-07-22
          相关资源
          最近更新 更多