在 yii2 Rest API 上发布时,基本身份验证返回消息:“用户名不能为空”,即使数据库有它

问题描述 投票:0回答:1

在 Yii2 中,我学会了创建 Rest API。我现在可以发布获取和更新数据。我最近添加了身份验证,我的令牌已被接受,但正在尝试从用户表中查找 useranme auth_key、password_hash 和电子邮件。我正在更新我的 Reading_schedule 表。 我目前正在使用邮递员来测试我的 Rest API 的 url 创建 一切都在没有身份验证的情况下正常工作,直到我最近在我的代码中添加了Basic Authentication

postman output

即使我将身份验证密钥令牌添加到授权中,它现在也会在 Postman 上显示此消息

[
    {
        "field": "username",
        "message": "Username cannot be blank."
    },
    {
        "field": "auth_key",
        "message": "Auth Key cannot be blank."
    },
    {
        "field": "password_hash",
        "message": "Password Hash cannot be blank."
    },
    {
        "field": "email",
        "message": "Email cannot be blank."
    }
]

这是我的模块 v1 下的控制器

<?php

namespace app\modules\v1\controllers;

use yii\rest\ActiveController;
use yii\web\Controller;

/**
 * ReadingSchedule controller for the `v1` module
 */
class ReadingScheduleController extends ActiveController
{
    public $modelClass="app\models\ReadingSchedule";
    
    public function behaviors() //override
    {
        $behaviors = parent::behaviors();
        $behaviors['authenticator'] = [            
            'class' => \yii\filters\auth\CompositeAuth::class,
            'authMethods' => [
                \yii\filters\auth\HttpBearerAuth::class,
                \yii\filters\auth\HttpBasicAuth::class,                
                [
                    'class' => \yii\filters\auth\CompositeAuth::class,
                ]
            ]             
            
        ];
        $behaviors['authenticator'] = [
            'class' => \yii\filters\auth\HttpBasicAuth::class,
            'auth' => [$this, 'auth']
        ];
        return $behaviors;
    }

    public function auth($username, $password)
    {
        return \app\models\User::findOne(['login' => $username, 'password' => $password]);
    }



    
}

这是我的用户模块,因为它指出我需要实现身份接口

<?php

namespace app\models;

use Yii;
use yii\web\IdentityInterface;

/**
 * This is the model class for table "user".
 *
 * @property int $id
 * @property string $username
 * @property string $auth_key
 * @property string|null $verification_token
 * @property string $password_hash
 * @property string|null $password_reset_token
 * @property string $email
 * @property int $status
 * @property string $created_at
 * @property string $updated_at
 */
class User extends \yii\db\ActiveRecord implements IdentityInterface
{

    const STATUS_DELETED = 0;
    const STATUS_INACTIVE = 9;
    const STATUS_ACTIVE = 10;
    /**
     * {@inheritdoc}
     */
    public static function tableName()
    {
        return 'user';
    }

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            ['status', 'default', 'value' => self::STATUS_ACTIVE],
            ['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_INACTIVE, self::STATUS_DELETED]],
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'username' => 'Username',
            'auth_key' => 'Auth Key',
            'verification_token' => 'Verification Token',
            'password_hash' => 'Password Hash',
            'password_reset_token' => 'Password Reset Token',
            'email' => 'Email',
            'status' => 'Status',
            'created_at' => 'Created At',
            'updated_at' => 'Updated At',
        ];
    }
    public static function findIdentity($id)
    {
        return static::findOne($id);
    }

    public static function findIdentityByAccessToken($token, $type = null)
    {
        return static::findOne(['auth_key' => $token]);
    }

    public function getId()
    {
        return $this->id;
    }

    public function getAuthKey()
    {
        return $this->auth_key;  // Updated case for property name
    }
  
    public function validateAuthKey($authKey)
    {
        return $this->auth_key === $authKey;  // Updated case for property name
    }
  }


php yii2
1个回答
0
投票

经过几个小时的研究,我尝试了 QueryParamAuth 作为示例身份验证。 我在使用 QueryParamAuth 的 Postman 中遇到的 422 数据验证错误消息可能是因为 即使我使用访问令牌进行身份验证,代码仍在尝试验证用户数据。以下是发生的情况以及解决方法:

错误原因:

Thw actionCreate 逻辑是为基于表单的身份验证而设计的,其中用户数据在请求正文中提交。它期望存在用户名、auth_key、password_hash 和电子邮件等字段。 QueryParamAuth 将访问令牌作为 URL 参数发送,而不是在请求正文中发送。 解决方案:

解决这个问题有两种主要方法:

1。 API 请求的单独逻辑:

创建一个单独的操作方法,专门用于使用 QueryParamAuth 处理 API 请求。 在这个新的操作方法中,从 URL 参数检索访问令牌(例如,$accessToken = Yii::$app->request->getQueryParam('access_token'))。 验证访问令牌(例如,在数据库中检查其有效性或使用令牌验证库)。 如果令牌有效,则继续创建阅读计划,无需验证用户数据。

2。 actionCreate 中的条件检查(修改方法):

修改现有的 actionCreate 逻辑以处理表单提交和 API 请求。 添加检查以查看请求方法是否为 POST 以及 URL 参数中是否存在访问令牌。 如果它是具有有效访问令牌的 API 请求,则绕过用户数据验证并继续创建阅读计划。否则,继续基于表单的验证逻辑。

这是使用条件检查方法修改后的actionCreate代码:

PHP
public function actionCreate()
{
    $model = new ReadingSchedule();

    $accessToken = Yii::$app->request->getQueryParam('access_token');

    if ($this->request->isPost() && $accessToken) {
        // API request with access token (bypass validation)
        $user = // Retrieve user based on valid access token (implement logic)
        if (!$user) {
            return $this->asJson(['message' => 'Invalid access token'], 401); // Unauthorized
        }

        // ... proceed with creating reading schedule using user object ...

    } else {
        // Regular form submission (validate user data)
        if ($model->load($this->request->post()) && $model->save()) {
            return $this->redirect(['view', 'id' => $model->id]);
        }
    }

    return $this->render('create', [
        'model' => $model,
    ]);
}

补充说明:

请记住实现基于有效访问令牌检索用户的逻辑($user = // 基于有效访问令牌检索用户(实现逻辑))。 根据您的具体需求调整错误处理(例如,返回 401 未经授权的响应)。

通过实现其中一种方法,您应该能够在 actionCreate 逻辑中使用 QueryParamAuth 处理表单提交和 API 请求。 API请求将绕过用户数据验证并依赖访问令牌进行身份验证。

© www.soinside.com 2019 - 2024. All rights reserved.