День 1641. #ЗаметкиНаПолях
Разработка API для Людей.
Часть 4. Шаблоны разработки. Окончание
Часть 1
Часть 2
Часть 3
Начало
3. Ответы
Возвращайте тип объекта
В большинстве случаев вызов API делается для получения или изменения данных. В последнем случае нормой является возврат изменённого ресурса. Например, если вы обновите email клиента, то в ответе вы ожидаете получить данные клиента с обновленным email.
Чтобы облегчить жизнь разработчикам, чётко укажите, что именно возвращается. Например, маршрут
/v1/customers/:customer/payment_methods/:payment_method
должен вернуть тип PaymentMethod для данного клиента. Это должно быть очевидно из маршрута, но на всякий случай, верните тип объекта в поле "object", чтобы избежать путаницы:
{
"id": "pm_123",
"object": "payment_method",
"created": 1672217299,
"customer": "cus_123",
…
}
Это очень помогает при поиске по логам или для добавления методов защитного программирования на клиенте:
if (response.Data.Object != "payment_method")
{
// не тот объект, который ожидался
return;
}
4. Безопасность
Используйте систему разрешений
Допустим, для крупного клиента вы добавили новую функцию, чтобы они протестировали её в бета-версии. Новый маршрут не задокументирован, о нём никто не знает, поэтому можно не волноваться. Несколько недель спустя вы вносите изменения в функцию, о которых попросил крупный клиент… И получаете серию гневных писем от других пользователей, у которых всё сломалось. Оказывается, о вашем секретном маршруте узнали другие.
Теперь надо не только решать проблемы клиентов. Теперь «бета»-функция фактически выпущена, т.к. об изменениях в ней придётся сообщать всем.
Если вы хотите, чтобы закрытые API оставались закрытыми, убедитесь, что к ним нельзя получить доступ, без соответствующих разрешений. Самый простой способ — привязать систему разрешений к ключу API. Если ключ API не авторизован для использования маршрута, верните сообщение об ошибке со статусом 403.
Сделайте идентификаторы неугадываемыми
Если вы разрабатываете API, который возвращает объекты со связанными с ними идентификаторами, убедитесь, что эти их нельзя угадать или каким-либо иным образом реконструировать. Если идентификаторы просто последовательные, то в лучшем случае вы непреднамеренно выдаёте ненужную информацию о бизнесе, в худшем случае - сильно подрываете безопасность.
Например, после покупки на сайте я получил идентификатор подтверждения заказа «10». Я могу сделать два предположения:
- У вас не такой большой бизнес, как вы, вероятно, заявляете.
- Я потенциально могу получить информацию о 9 предыдущих заказах (и обо всех будущих), так как знаю их идентификаторы. Если указанный ниже маршрут не защищён системой разрешений, можно угадать идентификатор и возможно получить закрытую информацию о других ваших клиентах:
https://api.example.com/v1/orders/9
Делайте идентификаторы неугадываемыми, например, используя UUID. Он, по сути, представляет собой строку случайных чисел и букв, что означает, что невозможно угадать, как будет выглядеть следующий идентификатор, основываясь на том, который у вас есть. Вы теряете в удобстве (гораздо проще говорить о «заказе 42», чем о «заказе 123e4567-e89b-12d3-a456-426614174000»), но вы компенсируете это преимуществами безопасности. Не забудьте сделать его понятным для человека, добавив префиксы объектов.
Источник: https://dev.to/stripe/common-design-patterns-at-stripe-1hb4