首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >YI2HTTPBasic认证RESTful API (Yii 2高级模板)

YI2HTTPBasic认证RESTful API (Yii 2高级模板)
EN

Stack Overflow用户
提问于 2015-04-26 16:49:18
回答 1查看 15.6K关注 0票数 10

REST在没有身份验证方法的情况下工作。现在,我想通过移动应用程序使用HTTP基本身份验证API请求来验证REST。我试过使用yii2指南,但它对我没有用。

基本上,移动用户需要使用用户名和密码登录,如果用户名和密码是正确的,用户需要登录,进一步的API请求需要用令牌进行验证。

调试findIdentityByAccessToken()函数时,$token等于用户名。用于检查HTTP基本请求的Postman扩展。用户表中的access_token字段为空。我需要手动保存它吗?如何返回access_token作为响应?

有理由同时使用三种方法(HttpBasicAuth、HttpBearerAuth、QueryParamAuth)吗?为什么?多么?

我的应用程序文件夹结构如下所示。

代码语言:javascript
复制
api
-config
-modules
--v1
---controllers
---models
-runtime
-tests
-web

backend
common
console
environments
frontend

api\modules\v1\Module.php

代码语言:javascript
复制
namespace api\modules\v1;
class Module extends \yii\base\Module
{
    public $controllerNamespace = 'api\modules\v1\controllers';

    public function init()
    {
        parent::init(); 
        \Yii::$app->user->enableSession = false;       
    }   
}

api\modules\v1\controllers\CountryController.php

代码语言:javascript
复制
namespace api\modules\v1\controllers;
use Yii;
use yii\rest\ActiveController;
use common\models\LoginForm;
use common\models\User;
use yii\filters\auth\CompositeAuth;
use yii\filters\auth\HttpBasicAuth;
use yii\filters\auth\HttpBearerAuth;
use yii\filters\auth\QueryParamAuth;

class CountryController extends ActiveController
{
    public $modelClass = 'api\modules\v1\models\Country';    

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

}

common\models\User.php

代码语言:javascript
复制
namespace common\models;

use Yii;
use yii\base\NotSupportedException;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;

class User extends ActiveRecord implements IdentityInterface
{
    const STATUS_DELETED = 0;
    const STATUS_ACTIVE = 10;

    public static function tableName()
    {
        return '{{%user}}';
    }

    public function behaviors()
    {
        return [
            TimestampBehavior::className(),
        ];
    }

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

    public static function findIdentity($id)
    {
        return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
    }

    public static function findIdentityByAccessToken($token, $type = null)
    {

        return static::findOne(['access_token' => $token]);
    }


}

用户表

代码语言:javascript
复制
id
username
auth_key
password_hash
password_reset_token
email
status
created_at
access_token

迁移用户表后添加了access_token

EN

回答 1

Stack Overflow用户

发布于 2015-08-21 08:30:40

您需要在保存用户之前设置令牌。在用户模型中,使用以下内容

代码语言:javascript
复制
public function beforeSave($insert)
{
    if (parent::beforeSave($insert)) {
        if ($this->isNewRecord) {
            $this->auth_key = Yii::$app->getSecurity()->generateRandomString();
        }
        return true;
    }
    return false;
}

现在您为每个用户提供了一个auth_key

要返回auth_key,需要在UserController中添加actionLogin

代码语言:javascript
复制
public function actionLogin()
{
    $post = Yii::$app->request->post();
    $model = User::findOne(["email" => $post["email"]]);
    if (empty($model)) {
        throw new \yii\web\NotFoundHttpException('User not found');
    }
    if ($model->validatePassword($post["password"])) {
        $model->last_login = Yii::$app->formatter->asTimestamp(date_create());
        $model->save(false);
        return $model; //return whole user model including auth_key or you can just return $model["auth_key"];
    } else {
        throw new \yii\web\ForbiddenHttpException();
    }
}

之后,在每个API请求中,您都会在头中发送auth_key,而不是发送用户名和密码。

代码语言:javascript
复制
$ curl -H "Authorization: Basic bd9615e2871c56dddd8b88b576f131f51c20f3bc" API_URL

若要检查auth_key是否有效,请在UserController行为中定义“身份验证器”。(不要忘记将“创建”、“登录”、“重新设置密码”排除在身份验证之外)

代码语言:javascript
复制
public function behaviors()
{
    return ArrayHelper::merge(
        parent::behaviors(), [
            'authenticator' => [
                'class' => CompositeAuth::className(),
                'except' => ['create', 'login', 'resetpassword'],
                'authMethods' => [
                    HttpBasicAuth::className(),
                    HttpBearerAuth::className(),
                    QueryParamAuth::className(),
                ],
            ],
        ]
    );
}
票数 19
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29880518

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档