Yii 2 RESTful API аутентифицируется с помощью OAuth2 (расширенный шаблон Yii 2)

REST API работает без методов аутентификации. Теперь я хотел аутентифицировать REST API с аутентификацией OAuth2 для запросов API через мобильное приложение. Я пробовал использовать руководство по yii2, но у меня это не сработало.

в основном мобильный пользователь должен войти в систему с именем пользователя и паролем, если имя пользователя и пароль верны, пользователь должен войти в систему, а дальнейший запрос API должен быть подтвержден с помощью токена.

Нужно ли мне создавать собственный клиент OAuth 2, подобный этому? Создание собственных клиентов аутентификации

Поле access_token в пользовательской таблице пусто. мне нужно сохранить его вручную? как вернуть access_token в качестве ответа?

есть ли причина для одновременного использования всех трех методов (HttpBasicAuth, HttpBearerAuth, QueryParamAuth), почему? как?

структура папок моего приложения выглядит так, как показано ниже.

api
-config
-modules
--v1
---controllers
---models
-runtime
-tests
-web

backend
common
console
environments
frontend

API \ модули \ v1 \ Module.php

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 \ модули \ v1 \ контроллеры \ CountryController.php

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;

/**
 * Country Controller API
 *
 * @author Budi Irawan <[email protected]>
 */
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;
    }

}

общий \ модели \ User.php

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]);
    }


}

таблица пользователей

id
username
auth_key
password_hash
password_reset_token
email
status
created_at
access_token

access_token был добавлен после переноса таблицы пользователей


person Chanuka Asanka    schedule 26.04.2015    source источник
comment
вы нашли решение?   -  person bdart    schedule 13.07.2015
comment
access_token необходимо сгенерировать вручную (например, sha1 (uniqid ())). В основном, после входа в систему (имя пользователя и пароль) пользователь получает токен доступа и использует его в одном из трех методов (HttpBasicAuth, HttpBearerAuth, QueryParamAuth) в каждом другом запросе к серверу.   -  person Tahiaji    schedule 10.09.2015


Ответы (3)


Я использую JWT для проверки запроса. По сути, JWT - это токен, который также содержит информацию о пользователе и о самом токене, например о сроке действия и сроке действия токена. Подробнее о JWT можно узнать здесь.

Процесс моего приложения выглядит следующим образом:

  • Во-первых, когда пользователь вошел в систему, создайте JWT для пользователя

    $key = base64_decode('some_random_string');
    
    $tokenId = base64_encode(mcrypt_create_iv(32));
    $issuedAt = time();
    $notBefore = $issuedAt + 5;
    $expire = $notBefore + 1800;
    
    $user = User::findByEmail($email);
    
    $data = [
        'iss' => 'your-site.com',
        'iat' => $issuedAt,
        'jti' => $tokenId,
        'nbf' => $notBefore,
        'exp' => $expire,
        'data' => [
            'id' => $user->id,
            'username' => $user->username,
            //put everything you want (that not sensitive) in here
        ]
    ];
    
    $jwt = JWT::encode($data, $key,'HS256');
    
    return $jwt;
    
  • Затем клиент (например, мобильное приложение) должен предоставлять токен в каждом запросе через заголовок авторизации. Заголовок будет выглядеть так:

    Authorization:Bearer [the JWT token without bracket]

  • В модели User добавьте такой метод для проверки токена:

    public static function findIdentityByAccessToken($token, $type = null) {
        $key = base64_decode('the same key that used in login function');
    
        try{
            $decoded = JWT::decode($token, $key, array('HS256'));
            return static::findByEmail($decoded->data->email);
        }catch (\Exception $e){
            return null;
        }
    }
    

    Библиотека JWT вызовет исключение, если токен больше не является недействительным (был подделан или истек срок его действия).

  • Затем добавьте это в функцию поведения в каждом контроллере:

    $behaviors['authenticator'] = [
        'class' => HttpBearerAuth::className(),
        'except' => ['login'] //action that you don't want to authenticate such as login
    ];
    

Вот и все! Надеюсь, эта работа понравилась вам. Да, и есть много JWT-библиотек, которые вы можете использовать (вы можете увидеть это здесь), но я лично используйте эту библиотеку от людей из firebase

person Luqman Sungkar    schedule 23.10.2016

Вы можете создать свою систему аутентификации, обычно это делаю я. Вы можете сохранить токены для каждого пользователя и после этого аутентифицировать пользователя с помощью этого токена. В каждом действии вы можете отправить этот токен для аутентификации пользователя.

person Vahe Galstyan    schedule 21.09.2015

Вам необходимо сделать следующее:

  • установите токен перед сохранением пользователя в модели User.
  • добавьте actionLogin в UserController, чтобы возвращать auth_key при входе пользователя в систему.
  • в каждом запросе API вы отправляете auth_key в заголовке вместо отправки имени пользователя и пароля.
  • чтобы проверить, действителен ли auth_key, определите «аутентификатор» в поведении UserController.

вы можете найти образцы кода в моем ответе на другой вопрос здесь

person Ahmad Yazji    schedule 08.08.2016