API RESTful - Аутентификация

В отличие от веб-приложений API-интерфейсы RESTful обычно не имеют гражданства, что означает, что сеансы или куки-файлы не должны использоваться. Поэтому каждый запрос должен иметь какие-то учетные данные для проверки подлинности, поскольку статус аутентификации пользователя может не поддерживаться сеансами или куки-файлами. Общей практикой является отправка секретного токена доступа с каждым запросом на аутентификацию пользователя. Поскольку токен доступа может использоваться для уникальной идентификации и аутентификации пользователя, запросы API всегда должны отправляться через HTTPS для предотвращения атак типа «человек-в-середине» (MitM).

Существует несколько способов отправки токена доступа:

  • HTTP Basic Auth: токен доступа отправляется как имя пользователя. Это следует использовать только тогда, когда токен доступа можно безопасно хранить на стороне потребителя API. Например, потребитель API - это программа, запущенная на сервере.
  • Параметр запроса: токен доступа отправляется в качестве параметра запроса в URL-адрес API, например, https://example.com/users?access-token=xxxxxxxx. Поскольку большинство веб-серверов будут хранить параметры запроса в журналах сервера, этот подход должен в основном использоваться для обслуживания запросов JSONP, которые не могут использовать HTTP-заголовки для отправки токенов доступа.
  • OAuth 2: токен доступа получен потребителем с сервера авторизации и отправлен на сервер API через HTTP-маркеры-носители, согласно протоколу OAuth2.

Yii поддерживает все вышеперечисленные методы аутентификации. Вы также можете легко создавать новые методы аутентификации.

Чтобы включить проверку подлинности для ваших API, выполните следующие действия:

  • Настройте компонент пользовательского приложения:
    • Установите для свойства enableSession значение false.
    • Установите для свойства loginUrl значение null, чтобы показывать ошибку HTTP 403 вместо перенаправления на страницу входа.
  • Укажите, какие методы проверки подлинности вы планируете использовать, настроив поведение аутентификатора в своих классах контроллера REST.
  • Внесите yii\web\IdentityInterface::findIdentityByAccessToken() в свой класс идентификации пользователя.

Шаг 1 не требуется, но рекомендуется для API RESTful, которые не должны иметь гражданства. Если параметр enableSession имеет значение false, статус проверки подлинности пользователя НЕ будет сохраняться для всех запросов с использованием сеансов. Вместо этого аутентификация будет выполняться для каждого запроса, что выполняется с помощью шагов 2 и 3.

use yii\filters\auth\HttpBasicAuth;

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

Если вы хотите поддерживать все три метода аутентификации, описанные выше, вы можете использовать Composite Auth следующим образом:

use yii\filters\auth\CompositeAuth;
use yii\filters\auth\HttpBasicAuth;
use yii\filters\auth\HttpBearerAuth;
use yii\filters\auth\QueryParamAuth;

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

Каждый элемент в authMethods должен быть именем класса метода auth или массивом конфигурации.

Реализация findIdentityByAccessToken() зависит от приложения. Например, в простых сценариях, когда каждый пользователь может иметь только один токен доступа, вы можете сохранить маркер доступа в столбце access_token таблицы user. Этот метод может быть легко реализован в классе User следующим образом:

use yii\db\ActiveRecord;
use yii\web\IdentityInterface;

class User extends ActiveRecord implements IdentityInterface
{
    public static function findIdentityByAccessToken($token, $type = null)
    {
        return static::findOne(['access_token' => $token]);
    }
}

После того как аутентификация включена, как описано выше, для каждого запроса API запрашиваемый контроллер будет пытаться аутентифицировать пользователя на своем этапе beforeAction().

Если аутентификация прошла успешно, контроллер выполнит другие проверки (такие как ограничение скорости, авторизация), а затем запустит действие. Идентифицированная информация об идентификаторе пользователя может быть восстановлена через Yii::$app->user->identity.

Если аутентификация завершается неудачно, ответ с состоянием HTTP 401 будет отправляться вместе с другими соответствующими заголовками (такими как заголовок WWW-Authenticate для HTTP Basic Auth).

Авторизация

После того, как пользователь аутентифицирован, вы, вероятно, захотите проверить, имеет ли он (она) разрешение на выполнение запрошенного действия для запрошенного ресурса.

Если ваши контроллеры расширяются от yii\rest\ActiveController, вы можете переопределить метод checkAccess() для выполнения проверки авторизации. Метод будет вызван встроенными действиями, предоставляемыми yii\rest\ActiveController.