You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Yii2 REST API添加Basic Authentication后提示字段不能为空

Yii2 REST API添加Basic Auth后POST接口提示User模型字段不能为空

在Yii2框架中已实现支持POST、GET、UPDATE的REST API,添加Basic Authentication后,用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."
    }
]

相关代码

ReadingSchedule控制器(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]);
    }
}

User模型(实现IdentityInterface)

<?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
    }
  }

解决方案

1. 修复Basic Auth的验证逻辑

控制器中的auth方法存在两个关键错误:

  • 查询用户时使用了不存在的login字段,实际表中用户名字段是username
  • 直接用明文密码匹配password字段,而数据库中存储的是加密后的password_hash

修改后的auth方法:

public function auth($username, $password)
{
    $user = \app\models\User::findOne(['username' => $username]);
    // 用Yii内置方法验证密码哈希
    if ($user && Yii::$app->security->validatePassword($password, $user->password_hash)) {
        return $user;
    }
    return null;
}

2. 清理Behaviors中的重复配置

原代码中先设置了CompositeAuth,随后又直接覆盖为HttpBasicAuth,且CompositeAuth中嵌套自身属于无效配置。清理后的behaviors方法:

public function behaviors()
{
    $behaviors = parent::behaviors();
    
    // 移除父类默认的认证器(如果存在)
    unset($behaviors['authenticator']);
    
    $behaviors['authenticator'] = [
        'class' => \yii\filters\auth\HttpBasicAuth::class,
        'auth' => [$this, 'auth'],
        // 可选:排除OPTIONS请求(避免预检请求被拦截)
        'except' => ['options']
    ];
    
    return $behaviors;
}

3. 补充User模型的密码处理逻辑(可选但必要)

为了确保用户密码的正确哈希存储,建议在User模型中添加密码设置方法:

/**
 * 生成密码哈希
 */
public function setPassword($password)
{
    $this->password_hash = Yii::$app->security->generatePasswordHash($password);
}

4. 验证Postman的Basic Auth配置

在Postman中选择Authorization类型为Basic Auth,直接填写用户名和密码即可,Postman会自动生成正确的Authorization请求头,避免手动构造时出现格式错误。


内容的提问来源于stack exchange,提问作者Stack Ultra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 23:54:57