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
相关产品推荐
相关产品推荐

