Yii2 Rest Authentication Bearer Post 数据缺失

Yii2 Rest Authentication Bearer Post Data missing

我正在研究 REST API。因此我准备了一个函数,通过 curl 将身份验证数据发送到 REST 服务器。我已经实施了两个身份验证选项。第一个是基本身份验证,第二个是通过令牌(Bearer)进行身份验证。

现在,我遇到了麻烦,因为在 REST 服务器上,如果通过令牌进行身份验证,REST 服务器不会接收到 POST 数据。身份验证本身正在运行,但 POST 数据将丢失。如果通过基本身份验证进行身份验证,REST 服务器将接收 POST 数据,没问题。

private function request($postdata){

    $url = $this->service_url_private;
    $curl = curl_init($url);
    $curl_post_data = $postdata;


    // check if token authentication is used
    if (array_key_exists('token', $postdata )){
        $token = $postdata['token'];
        $authorization = 'Authorization: Bearer ' . $token;
        // prepare curl for Bearer Token Authorization
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json' , $authorization));
    } else {
        // otherwise use BASIC authentication
        if (array_key_exists('email', $postdata )){
            $username = $postdata['email'];
        }
        if (array_key_exists('password', $postdata )){
            $password = $postdata['password'];
        }
        // prepare curl for Basic Authentication
        curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
        curl_setopt($curl, CURLOPT_USERPWD, "$username:$password");
    }

    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $curl_post_data);
    curl_setopt($curl, CURLINFO_HEADER_OUT, true); // Detail information for debugging
    curl_setopt($curl, CURLOPT_VERBOSE,true);
    $curl_response = curl_exec($curl); // Detail information for debugging
    $info = curl_getinfo($curl); // Detail information for debugging
    curl_close($curl);
    var_dump($info);
    return $curl_response;
}

此外,$curl_post_data 在调试时由客户端显示所有数据,然后用 curl_exec($curl) 执行其余调用。

可能是什么问题?

经过很多小时后,我找到了问题所在以及该问题的解决方案。

问题是:

curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json' , $authorization));

使用'Content-Type: application/json' 会导致丢失POST 数据信息。

解决方法是:

改变

'Content-Type: application/json' 

'Content-Type: application/x-www-form-urlencoded'

您可以使用 yii2 的 HttpBasicAuth 身份验证器行为来进行不记名令牌身份验证。

use yii\filters\auth\HttpBasicAuth;

public function behaviors()
{
    $behaviors = parent::behaviors();
    $behaviors['authenticator'] = [
        'class' => HttpBasicAuth::className(),
    ];
    return $behaviors;
}

Authentication

对于您建议的解决方案,您应该使用 json 请求解析器。

'request' => [
  'parsers' => [
    'application/json' => 'yii\web\JsonParser',
  ]
]

JsonParser

使用以下代码创建新文件并将其保存在命名空间中。然后使用此文件代替 \yii\filters\auth\HttpBearerAuth.

<?php
namespace api\filters\auth;

use api\components\HttpResponseCode;
use yii\db\Exception;
use yii\web\UnauthorizedHttpException;
class HttpBearerAuth extends \yii\filters\auth\HttpBearerAuth {
    /**
     * @var string the HTTP authentication realm
     */
    public $realm = 'api';
    public $pattern = FALSE;
    public function authenticate($user, $request, $response) {
        $authHeader = $request->getHeaders()->get('Authorization');
        //  Following condition is added to support fastcgi issue.
        if ($authHeader === null) {
            $authHeader = $this->getBearerAuthFromSession();
            $this->pattern = '/^Bearer\s+(.*?)$/';
        }
        if ($authHeader !== null) {
            if ($this->pattern) {
                preg_match($this->pattern, $authHeader, $matches);
                $identity = $user->loginByAccessToken($matches[1], get_class($this));
            } else {
                $identity = $user->loginByAccessToken($authHeader, get_class($this));
            }
            if ($identity === null) {
                return $this->handleFailure($response);
            }
            return $identity;
        }
        return null;
    }
    public function challenge($response) {

        $response->getHeaders()->set('WWW-Authenticate', "Bearer realm=\"{$this->realm}\"");
    }
    public function handleFailure($response) {
        $e = new UnauthorizedHttpException('Your request was made with invalid credentials.');
        throw $e;
    }
    /**
     * In HttpBearerAuth, some development environments do not populate Authorization header in the request;
     * The issue is caused by CGI/FastCGI mode in Apache.
     * Following lines must be added in api/web/.htaccess:
     * # Authorization Headers
     * RewriteCond %{HTTP:Authorization} .
     * RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
     * 
     * This function is used to access the following value in HttpBearerAuth to make it working :
     * $_SERVER[‘REDIRECT_HTTP_AUTHORIZATION’].
     * @return string|null
     */
    public function getBearerAuthFromSession(): ?string {
        if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) && $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] != "") {
            return $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
        }
        return NULL;
    }
}