Klimov Paul
10 years ago
25 changed files with 660 additions and 31 deletions
@ -0,0 +1,124 @@
|
||||
Аутентификация |
||||
============== |
||||
|
||||
В отличие от Web-приложений, RESTful API обычно не сохраняют информацию о состоянии, а это означает, что сессии и куки |
||||
использовать не следует. Следовательно, раз состояние аутентификации пользователя не может быть сохранено в сессиях или куках, |
||||
каждый запрос должен приходить вместе с определенным видом параметров аутентификации. Общепринятая практика состоит в том, |
||||
что для аутентификации пользователя с каждый запросом отправляется секретный токен доступа. Так как токен доступа |
||||
может использоваться для уникальной идентификации и аутентификации пользователя, **запросы к API всегда должны отсылаться |
||||
через протокол HTTPS, чтобы предотвратить атаки «человек посередине» (англ. "man-in-the-middle", MitM)**. |
||||
|
||||
Есть различные способы отправки токена доступа: |
||||
|
||||
* [HTTP Basic Auth](http://en.wikipedia.org/wiki/Basic_access_authentication): токен доступа |
||||
отправляется как имя пользователя. Такой подход следует использовать только в том случае, когда токен доступа может быть безопасно сохранен |
||||
на стороне абонента API. Например, если API используется программой, запущенной на сервере. |
||||
* Параметр запроса: токен доступа отправляется как параметр запроса в URL-адресе API, т.е. примерно таким образом: |
||||
`https://example.com/users?access-token=xxxxxxxx`. Так как большинство Web-серверов сохраняют параметры запроса в своих логах, |
||||
такой подход следует применять только при работе с `JSONP`-запросами, которые не могут отправлять токены доступа |
||||
в HTTP-заголовках. |
||||
* [OAuth 2](http://oauth.net/2/): токен доступа выдается абоненту API сервером авторизации |
||||
и отправляется API-серверу через [HTTP Bearer Tokens](http://tools.ietf.org/html/rfc6750), |
||||
в соответствии с протоколом OAuth2. |
||||
|
||||
Yii поддерживает все выше перечисленные методы аутентификации. Вы также можете легко создавать новые методы аутентификации. |
||||
|
||||
Чтобы включить аутентификацию для ваших API, выполните следующие шаги: |
||||
|
||||
1. У компонента приложения `user` установите свойство [[yii\web\User::enableSession|enableSession]] равным false. |
||||
2. Укажите, какие методы аутентификации вы планируете использовать, настроив поведение `authenticator` |
||||
в ваших классах REST-контроллеров. |
||||
3. Реализуйте метод [[yii\web\IdentityInterface::findIdentityByAccessToken()]] *в вашем [[yii\web\User::identityClass|классе UserIdentity]]*. |
||||
|
||||
Шаг 1 не обязателен, но рекомендуется его все-таки выполнить, так как RESTful API не должны сохранять информацию о состоянии клиента. Когда свойство [[yii\web\User::enableSession|enableSession]] |
||||
установлено в false, состояние аутентификации пользователя НЕ БУДЕТ постоянно |
||||
сохраняться между запросами с использованием сессий. Вместо этого аутентификация будет выполняться для каждого запроса, что достигается шагами 2 и 3. |
||||
|
||||
> Подсказка: если вы разрабатываете RESTful API в пределах приложения, вы можете настроить свойство |
||||
[[yii\web\User::enableSession|enableSession]] компонента приложения `user` в конфигурации приложения. Если вы разрабатываете |
||||
RESTful API как модуль, можете добавить следующую строчку в метод `init()` модуля: |
||||
> ```php |
||||
public function init() |
||||
{ |
||||
parent::init(); |
||||
\Yii::$app->user->enableSession = false; |
||||
} |
||||
``` |
||||
|
||||
Например, для использования HTTP Basic Auth, вы можете настроить свойство `authenticator` следующим образом: |
||||
|
||||
```php |
||||
use yii\filters\auth\HttpBasicAuth; |
||||
|
||||
public function behaviors() |
||||
{ |
||||
$behaviors = parent::behaviors(); |
||||
$behaviors['authenticator'] = [ |
||||
'class' => HttpBasicAuth::className(), |
||||
]; |
||||
return $behaviors; |
||||
} |
||||
``` |
||||
|
||||
Если вы хотите включить поддержку всех трех описанных выше методов аутентификации, можете использовать `CompositeAuth`: |
||||
|
||||
```php |
||||
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` должен быть названием класса метода аутентификации или массивом настроек. |
||||
|
||||
|
||||
Реализация метода `findIdentityByAccessToken()` определяется особенностями приложения. Например, в простом варианте, |
||||
когда у каждого пользователя есть только один токен доступа, вы можете хранить этот токен в поле `access_token` |
||||
таблицы пользователей. В этом случае метод `findIdentityByAccessToken()` может быть легко реализован в классе `User` следующим образом: |
||||
|
||||
```php |
||||
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). |
||||
|
||||
|
||||
## Авторизация <a name="authorization"></a> |
||||
|
||||
После аутентификации пользователя вы, вероятно, захотите проверить, есть ли у него или у нее разрешение на выполнение запрошенного |
||||
действия с запрошенным ресурсом. Этот процесс называется *авторизацией* и подробно описан |
||||
в разделе [Авторизация](security-authorization.md). |
||||
|
||||
Если ваши контроллеры унаследованы от [[yii\rest\ActiveController]], вы можете переопределить |
||||
метод [[yii\rest\Controller::checkAccess()|checkAccess()]] для выполнения авторизации. Этот метод будет вызываться |
||||
встроенными действиями, предоставляемыми контроллером [[yii\rest\ActiveController]]. |
@ -0,0 +1,152 @@
|
||||
Контроллеры |
||||
=========== |
||||
|
||||
После создания классов ресурсов и настройки способа форматирования ресурсных данных следующим шагом |
||||
является создание действий контроллеров для предоставления ресурсов конечным пользователям через RESTful API. |
||||
|
||||
В Yii есть два базовых класса контроллеров для упрощения вашей работы по созданию RESTful-действий: |
||||
[[yii\rest\Controller]] и [[yii\rest\ActiveController]]. Разница между этими двумя контроллерами в том, |
||||
что у последнего есть набор действий по умолчанию, который специально создан для работы с ресурсами, |
||||
представленными [Active Record](db-active-record.md). Так что если вы используете [Active Record](db-active-record.md) |
||||
и вас устраивает предоставленный набор встроенных действий, вы можете унаследовать классы ваших контроллеров |
||||
от [[yii\rest\ActiveController]], что позволит вам создать полноценные RESTful API, написав минимум кода. |
||||
|
||||
[[yii\rest\Controller]] и [[yii\rest\ActiveController]] имеют следующие возможности, некоторые из которых |
||||
будут подробно описаны в следующих нескольких разделах: |
||||
|
||||
* Проверка HTTP-метода; |
||||
* [Согласование содержимого и форматирование данных](rest-response-formatting.md); |
||||
* [Аутентификация](rest-authentication.md); |
||||
* [Ограничение частоты запросов](rest-rate-limiting.md). |
||||
|
||||
[[yii\rest\ActiveController]], кроме того, предоставляет следующие возможности: |
||||
|
||||
* Набор наиболее употребительных действий: `index`, `view`, `create`, `update`, `delete`, `options`; |
||||
* Авторизация пользователя для запрашиваемых действия и ресурса. |
||||
|
||||
|
||||
## Создание классов контроллеров <a name="creating-controller"></a> |
||||
|
||||
При создании нового класса контроллера в имени класса обычно используется |
||||
название типа ресурса в единственном числе. Например, контроллер, отвечающий за предоставление информации о пользователях, |
||||
можно назвать `UserController`. |
||||
|
||||
Создание нового действия похоже на создание действия для Web-приложения. Единственное отличие в том, |
||||
что в RESTful-действиях вместо рендера результата в представлении с помощью вызова метода `render()` |
||||
вы просто возвращает данные. Выполнение преобразования исходных данных в запрошенный формат ложится на |
||||
[[yii\rest\Controller::serializer|сериализатор]] и [[yii\web\Response|объект ответа]]. |
||||
Например: |
||||
|
||||
```php |
||||
public function actionView($id) |
||||
{ |
||||
return User::findOne($id); |
||||
} |
||||
``` |
||||
|
||||
|
||||
## Фильтры <a name="filters"></a> |
||||
|
||||
Большинство возможностей RESTful API, предоставляемых [[yii\rest\Controller]], реализовано на основе [фильтров](structure-filters.md). |
||||
В частности, следующие фильтры будут выполняться в том порядке, в котором они перечислены: |
||||
|
||||
* [[yii\filters\ContentNegotiator|contentNegotiator]]: обеспечивает согласование содержимого, более подробно описан |
||||
в разделе [Форматирование ответа](rest-response-formatting.md); |
||||
* [[yii\filters\VerbFilter|verbFilter]]: обеспечивает проверку HTTP-метода; |
||||
* [[yii\filters\AuthMethod|authenticator]]: обеспечивает аутентификацию пользователя, более подробно описан |
||||
в разделе [Аутентификация](rest-authentication.md); |
||||
* [[yii\filters\RateLimiter|rateLimiter]]: обеспечивает ограничение частоты запросов, более подробно описан |
||||
в разделе [Ограничение частоты запросов](rest-rate-limiting.md). |
||||
|
||||
Эти именованные фильтры объявлены в методе [[yii\rest\Controller::behaviors()|behaviors()]]. |
||||
Вы можете переопределить этот метод для настройки отдельных фильтров, отключения каких-то из них или для добавления ваших собственных фильтров. |
||||
Например, если вы хотите использовать только базовую HTTP-аутентификацию, вы можете написать такой код: |
||||
|
||||
```php |
||||
use yii\filters\auth\HttpBasicAuth; |
||||
|
||||
public function behaviors() |
||||
{ |
||||
$behaviors = parent::behaviors(); |
||||
$behaviors['authenticator'] = [ |
||||
'class' => HttpBasicAuth::className(), |
||||
]; |
||||
return $behaviors; |
||||
} |
||||
``` |
||||
|
||||
|
||||
## Наследование от `ActiveController` <a name="extending-active-controller"></a> |
||||
|
||||
Если ваш класс контроллера наследуется от [[yii\rest\ActiveController]], вам следует установить |
||||
значение его свойства [[yii\rest\ActiveController::modelClass||modelClass]] равным имени класса ресурса, |
||||
который вы планируете обслуживать с помощью этого контроллера. Класс ресурса должен быть унаследован от [[yii\db\ActiveRecord]]. |
||||
|
||||
|
||||
### Настройка действий <a name="customizing-actions"></a> |
||||
|
||||
По умолчанию [[yii\rest\ActiveController]] предоставляет набор из следующих действий: |
||||
|
||||
* [[yii\rest\IndexAction|index]]: постраничный список ресурсов; |
||||
* [[yii\rest\ViewAction|view]]: возвращает подробную информацию об указанном ресурсе; |
||||
* [[yii\rest\CreateAction|create]]: создание нового ресурса; |
||||
* [[yii\rest\UpdateAction|update]]: обновление существующего ресурса; |
||||
* [[yii\rest\DeleteAction|delete]]: удаление указанного ресурса; |
||||
* [[yii\rest\OptionsAction|options]]: возвращает поддерживаемые HTTP-методы. |
||||
|
||||
Все эти действия объявляются в методе [[yii\rest\ActiveController::actions()|actions()]]. |
||||
Вы можете настроить эти действия или отключить какие-то из них, переопределив метод `actions()`, как показано ниже: |
||||
|
||||
```php |
||||
public function actions() |
||||
{ |
||||
$actions = parent::actions(); |
||||
|
||||
// отключить действия "delete" и "create" |
||||
unset($actions['delete'], $actions['create']); |
||||
|
||||
// настроить подготовку провайдера данных с помощью метода "prepareDataProvider()" |
||||
$actions['index']['prepareDataProvider'] = [$this, 'prepareDataProvider']; |
||||
|
||||
return $actions; |
||||
} |
||||
|
||||
public function prepareDataProvider() |
||||
{ |
||||
// подготовить и вернуть провайдер данных для действия "index" |
||||
} |
||||
``` |
||||
|
||||
Чтобы узнать, какие опции доступны для настройки классов отдельных действий, обратитесь к соответствующим разделам справочника классов. |
||||
|
||||
|
||||
### Выполнение контроля доступа <a name="performing-access-check"></a> |
||||
|
||||
При предоставлении ресурсов через RESTful API часто бывает нужно проверять, имеет ли текущий пользователь разрешение |
||||
на доступ к запрошенному ресурсу (или ресурсам) и манипуляцию им (ими). Для [[yii\rest\ActiveController]] эта задача может быть решена |
||||
переопределением метода [[yii\rest\ActiveController::checkAccess()|checkAccess()]] следующим образом: |
||||
|
||||
```php |
||||
/** |
||||
* Проверяет права текущего пользователя. |
||||
* |
||||
* Этот метод должен быть переопределен, чтобы проверить, имеет ли текущий пользователь |
||||
* право выполнения указанного действия над указанной моделью данных. |
||||
* Если у пользователя нет доступа, следует выбросить исключение [[ForbiddenHttpException]]. |
||||
* |
||||
* @param string $action ID действия, которое надо выполнить |
||||
* @param \yii\base\Model $model модель, к которой нужно получить доступ. Если null, это означает, что модель, к которой нужно получить доступ, отсутствует. |
||||
* @param array $params дополнительные параметры |
||||
* @throws ForbiddenHttpException если у пользователя нет доступа |
||||
*/ |
||||
public function checkAccess($action, $model = null, $params = []) |
||||
{ |
||||
// проверить, имеет ли пользователь доступ к $action и $model |
||||
// выбросить ForbiddenHttpException, если доступ следует запретить |
||||
} |
||||
``` |
||||
|
||||
Метод `checkAccess()` будет вызван действиями по умолчанию контроллера [[yii\rest\ActiveController]]. Если вы создаете |
||||
новые действия и хотите в них выполнять контроль доступа, вы должны вызвать этот метод явно в своих новых действиях. |
||||
|
||||
> Подсказка: вы можете реализовать метод `checkAccess()` с помощью ["Контроля доступа на основе ролей" (RBAC)](security-authorization.md). |
@ -0,0 +1,78 @@
|
||||
Маршрутизация |
||||
============= |
||||
|
||||
Имея готовые классы ресурсов и контроллеров, можно получить доступ к ресурсам, используя URL вроде |
||||
`http://localhost/index.php?r=user/create`, подобно тому, как вы это делаете с обычными Web-приложениями. |
||||
|
||||
На деле вам обычно хочется включить «красивые» URL-адреса и использовать все преимущества HTTP-методов (HTTP-verbs). |
||||
Например, чтобы запрос `POST /users` означал обращение к действию `user/create`. |
||||
Это может быть легко сделано с помощью настройки компонента приложения `urlManager` в |
||||
конфигурации приложения следующим образом: |
||||
|
||||
```php |
||||
'urlManager' => [ |
||||
'enablePrettyUrl' => true, |
||||
'enableStrictParsing' => true, |
||||
'showScriptName' => false, |
||||
'rules' => [ |
||||
['class' => 'yii\rest\UrlRule', 'controller' => 'user'], |
||||
], |
||||
] |
||||
``` |
||||
|
||||
Главная новинка в коде выше по сравнению с управлением URL-адресами в Web-приложениях состоит в использовании |
||||
[[yii\rest\UrlRule]] для маршрутизации запросов к RESTful API. Этот особый класс URL-правил будет |
||||
создавать целый набор дочерних URL-правил для поддержки маршрутизации и создания URL-адресов для указанного контроллера (или контроллеров). |
||||
Например, приведенный выше код является приближенным аналогом следующего набора правил: |
||||
|
||||
```php |
||||
[ |
||||
'PUT,PATCH users/<id>' => 'user/update', |
||||
'DELETE users/<id>' => 'user/delete', |
||||
'GET,HEAD users/<id>' => 'user/view', |
||||
'POST users' => 'user/create', |
||||
'GET,HEAD users' => 'user/index', |
||||
'users/<id>' => 'user/options', |
||||
'users' => 'user/options', |
||||
] |
||||
``` |
||||
|
||||
Этим правилом поддерживаются следующие точки входа в API: |
||||
|
||||
* `GET /users`: разбитый на страницы список всех пользователей; |
||||
* `HEAD /users`: общая информация по списку пользователей; |
||||
* `POST /users`: создание нового пользователя; |
||||
* `GET /users/123`: подробная информация о пользователе 123; |
||||
* `HEAD /users/123`: общая информация о пользователе 123; |
||||
* `PATCH /users/123` и `PUT /users/123`: обновление пользователя 123; |
||||
* `DELETE /users/123`: удаление пользователя 123; |
||||
* `OPTIONS /users`: список HTTP-методов, поддерживаемые точкой входа `/users`; |
||||
* `OPTIONS /users/123`: список HTTP-методов, поддерживаемые точкой входа `/users/123`. |
||||
|
||||
Вы можете настроить опции `only` и `except`, явно указав для них список действий, которые поддерживаются или |
||||
которые должны быть отключены, соответственно. Например: |
||||
|
||||
```php |
||||
[ |
||||
'class' => 'yii\rest\UrlRule', |
||||
'controller' => 'user', |
||||
'except' => ['delete', 'create', 'update'], |
||||
], |
||||
``` |
||||
|
||||
Вы также можете настроить опции `patterns` или `extraPatterns` для переопределения существующих шаблонов или добавления новых шаблонов, поддерживаемых этим правилом. |
||||
Например, для включения нового действия `search` в точке входа `GET /users/search` настройте опцию `extraPatterns` следующим образом: |
||||
|
||||
```php |
||||
[ |
||||
'class' => 'yii\rest\UrlRule', |
||||
'controller' => 'user', |
||||
'extraPatterns' => [ |
||||
'GET search' => 'search', |
||||
], |
||||
``` |
||||
|
||||
Как вы могли заметить, ID контроллера `user` в этих точках входа используется в форме множественного числа (как `users`). |
||||
Это происходит потому, что [[yii\rest\UrlRule]] автоматически приводит идентификаторы контроллеров к множественной форме для использования в точках входа. |
||||
Вы можете отключить такое поведение, назначив свойству [[yii\rest\UrlRule::pluralize]] значение false, или, если вы хотите использовать |
||||
какие-то особые имена, вы можете настроить свойство [[yii\rest\UrlRule::controller]]. |
Loading…
Reference in new issue