RESTful дизайн / логин или / регистрация ресурсов?

69

Я разрабатывал веб-приложение, а затем остановился, чтобы подумать о том, как мой api должен быть спроектирован как веб-сервис RESTful. На данный момент большая часть моего URI является общей и может применяться к различным веб-приложениям:

GET  /logout   // destroys session and redirects to /
GET  /login    // gets the webpage that has the login form
POST /login    // authenticates credentials against database and either redirects home with a new session or redirects back to /login
GET  /register // gets the webpage that has the registration form
POST /register // records the entered information into database as a new /user/xxx
GET  /user/xxx // gets and renders current user data in a profile view
POST /user/xxx // updates new information about user

У меня такое чувство, что я делаю много неправильного здесь, после того, как тыкнул SO и Google.

Начиная с /logout, возможно, так как я действительно не GET ничего - может быть более подходящим для POST запроса /logout, уничтожить сеанс, а затем GET перенаправить. И должен ли срок /logout оставаться?

Как насчет /login и /register. Я мог бы изменить /register на /registration, но это не повлияет на то, как работает мой сервис, если у него есть более глубокие проблемы.

Теперь я замечаю, что никогда не показываю ресурс /user. Возможно, это можно было бы использовать как-то. Например, возьмите пользователя myUser:

foo.com/user/myUser

или

foo.com/user

Конечный пользователь не требует дополнительной многословности в URI. Однако какой из них более привлекателен визуально?

Я заметил некоторые другие вопросы здесь о SO об этом бизнесе REST, но я был бы очень признателен за некоторые рекомендации относительно того, что я здесь изложил, если это возможно.

Спасибо!

UPDATE:

Мне также хотелось бы получить некоторые мнения о:

/user/1

против

/user/myUserName
  • 5
    Я согласен с тем, что выход из системы является вызовом POST, потому что он действительно что-то меняет, а не просто получает ресурс.
  • 2
    Смотрите также: stackoverflow.com/questions/3521290/logout-get-or-post
Теги:
rest
web-services
http
restful-url

7 ответов

47
Лучший ответ

Одна вещь торчит, в частности, как не REST-ful: использование запроса GET для выхода из системы.

(из http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Safe_methods)

Некоторые методы (например, HEAD, GET, OPTIONS и TRACE) определяются как безопасные, что означает, что они предназначены только для извлечения информации и не должны изменять состояние сервера. Другими словами, они не должны иметь побочных эффектов, помимо относительно безвредных эффектов, таких как ведение журнала, кеширование, подача рекламных баннеров или увеличение веб-счетчика. [...]

[... H] andling [запросов GET] сервером никак не ограничивается технически. Поэтому небрежное или преднамеренное программирование может привести к нетривиальным изменениям на сервере. Это обескураживает, поскольку это может вызвать проблемы для веб-кеширования, поисковых систем и других автоматизированных агентов [...]

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

http://en.wikipedia.org/wiki/Post/Redirect/Get

http://en.wikipedia.org/wiki/HTTP_303

Отредактируйте проблемы с адресами:

"Как мне создавать свои ресурсы?" является важным вопросом для меня; "Как мне создавать URL-адреса?" рассматривается в двух областях:

URL-адреса, которые пользователи будут видеть, не должны быть слишком уродливыми и значимыми, если это возможно; если вы хотите, чтобы файлы cookie отправлялись в запросах на какой-либо ресурс, но не на других, вам нужно структурировать пути и пути к файлам cookie.

Если JRandomUser хочет посмотреть его собственный профиль и вы хотите, чтобы URL был более симпатичным, чем foo.com/user/JRandomUser или foo.com/user/(JRandom numeric user id here), вы могли бы сделать отдельный URL-адрес только для того, чтобы пользователь мог посмотреть свою собственную информацию:

GET foo.com/profile /*examines cookies to figure out who 
                     * is logged in (SomeUser) and then 
                     * displays the same response as a
                     * GET to foo.com/users/SomeUser.
                     */

Я бы требовал невежества гораздо легче, чем мудрости по этому вопросу, но вот несколько соображений дизайна ресурсов:

  • Потребитель: какие ресурсы предназначены для просмотра непосредственно в браузере, загружаются через XHR или доступны другим клиентам?
  • Доступ/идентификатор: зависит ли ответ от файлов cookie или рефереров?
  • 1
    Отличный ответ, спасибо! Если бы я собирался реализовать ваше отдельное предложение по URL ( GET foo.com/profile/ ), было бы это частью, как предложил momo, уровня представления? Другими словами, что именно должен возвращать этот GET ? Веб-страница или какой-то JSON?
  • 2
    Ах, я думаю, что я вижу сейчас. Ответ Момо действительно прояснил ситуацию. Таким образом, RESTful API создан для того, чтобы позволить нескольким платформам GET , POST , PUT и DELETE ресурсы. Веб-сайт - это просто еще одна платформа для доступа к API. Другими словами, дизайн URL сайта совершенно отличается от дизайна RESTful API. Пожалуйста, скажите мне, если я все еще не прав, ха-ха.
Показать ещё 1 комментарий
82

RESTful может использоваться как ориентир для создания URL-адресов, и вы можете создавать сеансы и ресурсы пользователей:

  • GET /session/new получает веб-страницу с формой входа
  • POST /session аутентифицирует учетные данные для базы данных
  • DELETE /session уничтожает сеанс и перенаправляет на /
  • GET /users/new получает веб-страницу с регистрационной формой
  • POST /users записывает введенную информацию в базу данных как новый /user/xxx
  • GET /users/xxx//получает и отображает текущие пользовательские данные в представлении профиля
  • POST /users/xxx//обновляет новую информацию о пользователе

Они могут быть множественными или единственными (я не уверен, какой из них правильный). Обычно я использовал /users для пользовательской индексной страницы (как и ожидалось) и /sessions, чтобы узнать, кто вошел в систему (как и ожидалось).

Использование имени в URL вместо числа (/users/43 vs. /users/joe) обычно обусловлено желанием быть более дружелюбным к пользователям или поисковым системам, а не к каким-либо техническим требованиям. Все в порядке, но я бы рекомендовал вам быть последовательным.

Я думаю, что если вы пойдете с регистром /login/logout или sign(in|up|out), это не сработает с успокоительной терминологией.

  • 5
    Потрясающие! Мне нравится, как вы называете эти ресурсы; это довольно чисто. Хотя, насколько я слышал, не добавляется /new не добавляется в GET /session/ non RESTful? Я слышал, что глаголы обычно оставляют за глаголами HTTP ( GET , POST и т. Д.).
  • 2
    @ Зач новый не глагол. В данном случае это подресурс сессии.
Показать ещё 4 комментария
37

Сеансы не RESTful

  • Да, я знаю. Это делается, как правило, с OAuth, но на самом деле сеансы не RESTful. Вы не должны иметь ресурс /login/logout, потому что у вас не должно быть сеансов.

  • Если вы собираетесь это сделать, сделайте его RESTful. Ресурсы - существительные и /login и/logout - не существительные. Я бы пошел с /session. Это делает создание и удаление более естественным действием.

  • POST и GET для сеансов легко. Если вы отправляете пользователя/пароль в качестве переменных, я бы использовал POST, потому что я не хочу, чтобы пароль был отправлен как часть URI. Он появится в журналах и, возможно, будет выставлен по проводам. Вы также рискуете, что программное обеспечение завершится с ошибкой GET args.

  • Обычно я использую Basic Auth или no Auth с сервисами REST.

Создание пользователей

  • Это один ресурс, поэтому вам не нужно/зарегистрироваться.

    • POST/user - создает пользователя, если запрашивающий не может указать идентификатор
    • PUT/user/xxx - Создайте или обновите пользователя, если вы заранее знаете идентификатор.
    • GET/user - список x идентификаторов пользователей
    • GET/user/xxx - ПОЛУЧИТ детали пользователя с идентификатором xxx
    • DELETE/user/xxx - Удалить пользователя с идентификатором xxx
  • Какой тип идентификатора используется, это сложный вопрос. Вы должны думать об обеспечении уникальности, о повторном использовании старых идентификаторов, которые были DELETEd. Например, вы не хотите использовать эти идентификаторы как внешние ключи на бэкэнд, если идентификаторы будут переработаны (если это вообще возможно). Однако для внешнего/внутреннего преобразования идентификаторов вы можете искать, чтобы уменьшить требования к бэкэнд.

  • 4
    Это лучший ответ. / login и / logout не являются ресурсами и нарушают идею REST.
  • 1
    Msgstr "Сеансы не RESTful, поэтому не используйте аутентификацию". Okaay ...
Показать ещё 3 комментария
13

Я просто расскажу о своем опыте интеграции различных веб-сервисов REST для своих клиентов, будь то для мобильных приложений или для связи между серверами и серверами, а также для создания REST API для других. Вот несколько замечаний, которые я собрал из других REST API других людей, а также те, которые мы создали сами:

  • Когда мы говорим API, он обычно относится к набору программных интерфейсов, а не к уровню представления. REST также ориентирован на данные, а не ориентирован на презентацию. Тем не менее большинство REST возвращают данные в виде JSON или XML и редко возвращают определенный уровень представления. Эта характеристика (возврата данных, а не прямой веб-страницы) дает возможность REST выполнять многоканальную доставку. Это означает, что один и тот же веб-сервис может отображаться в формате HTML, iOS, Android или даже использоваться как комбинация серверов и серверов.
  • Очень редко комбинировать как HTML, так и REST в качестве URL-адреса. По умолчанию REST - это мысли как службы и не имеющие уровня представления. Это работа для тех, кто потребляет веб-службы для предоставления данных из услуг, которые они называют, в соответствии с тем, что они хотят. К тому моменту ваш URL-адрес ниже соответствует большинству проектов, основанных на REST, которые я встречал до сих пор (а также стандарты, такие как те, которые поступают из Facebook или Twitter).
 
GET  /register // gets the webpage that has the registration form
  • Продолжая предыдущую точку, также редко (и я не встречался) для службы на основе REST для перенаправления, такой как предложенные ниже:
 
GET  /logout   // destroys session and redirects to /
POST /login    // authenticates credentials against database and either redirects home with a new session or redirects back to /login
 

Поскольку REST разрабатываются как службы, такие функции, как вход и выход из системы, обычно возвращают результат успеха/отказа (обычно в формате JSON или XML), который затем потребитель интерпретирует. Такая интерпретация может включать перенаправление на соответствующую веб-страницу, как вы упомянули

  • В REST URL означает действия, которые были предприняты. По этой причине мы должны устранить как можно большую двусмысленность. Хотя в вашем случае законно иметь GET и POST, которые имеют один и тот же путь (например,/register), которые выполняют разные действия, такой дизайн вводит двусмысленность в предоставляемых услугах и может запутать потребителя ваших услуг. Например, такие URL-адреса, как тот, который вы вводите ниже, не являются идеальными для служб на основе REST.
 
GET  /register // gets the webpage that has the registration form
POST /register // records the entered information into database as a new /user/xxx

Вот некоторые моменты из того, что я имел в виду. Я надеюсь, что это может дать вам некоторые идеи.

Теперь, насколько это возможно для реализации вашего REST, это типичная реализация, с которой я столкнулся:

  • GET  /logout  
    

    Выполнить выход в бэкэнд и вернуть JSON для обозначения успеха/отказа операции

  • POST /login
    

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

  • POST /register
    

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

  • GET  /user/xxx
    

    Получить профиль пользователя и вернуть формат данных JSON для профиля пользователя

  • POST /user/xxx 
    // renamed to 
    POST /updateUser/xxx
    

    Опубликовать обновленную информацию о профиле как формате JSON и обновить информацию в бэкэнд. Вернуть успех/отказ вызывающему абоненту

  • 3
    Да, если вы интегрируете свой REST API с приложением на основе HTML (через Javascript и AJAX), вы получите огромные преимущества, поскольку JSON анализируется Javascript изначально. В Android / Java анализировать JSON проще и проще, чем XML.
  • 9
    GET / выход опасен. GET должен быть идемпотентом. Кроме того, браузеры любят предварительно выбирать <a> hrefs, что позволит вам выйти из системы!
3

Использование и разработка API-интерфейсов - это не только визуально привлекательные URL-адреса, но и URL-адреса, которые имеют смысл. Для регистрации пользователя/входа в систему я использовал их в прошлом:

GET  /user          // Get multiple user info (limit ~10)
GET  /user/1        // Get single user info
POST /user          // Create user (registration)
PUT  /user/1        // Edit user
POST /user/1/login  // Login (could be GET, but I like sending more secure params by POST)
GET  /user/1/logout // Logout
  • 5
    Используйте HTTPS, если хотите безопасности, хорошо?
  • 9
    Моя точка зрения заключалась в том, что POST не более безопасен, чем GET ( за исключением информации, записываемой в файлы журналов, но они должны быть прочитаны только людьми с высоким уровнем доверия). Настоящая безопасность обеспечивается защитой канала с помощью SSL (т. Е. С использованием HTTPS); причина использования POST вместо PUT заключается в идемпотентности операции. (OTOH, я никогда не видел сеансов входа в систему, управляемых с помощью REST; обычно они, кажется, настраиваются до перехода на RESTful-часть сайта.)
Показать ещё 2 комментария
2

Я считаю, что это подход RESTful к аутентификации. Для LogIn вы используете HttpPut. Этот метод HTTP может использоваться для создания, когда ключ предоставляется, а повторные вызовы являются идемпотентными. Для LogOff вы указываете тот же путь в методе HttpDelete. Нет глаголов. Надлежащая коллективная плюрализация. Методы HTTP поддерживают цель.

[HttpPut]
[Route("sessions/current")]
public IActionResult LogIn(LogInModel model) { ... }

[HttpDelete]
[Route("sessions/current")]
public IActionResult LogOff() { ... }

При желании вы можете заменить ток на активный.

2

Я бы рекомендовал использовать URL-адрес учетной записи пользователя, похожий на твиттер, где URL-адрес учетной записи пользователя был бы похож на foo.com/myUserName так же, как вы можете попасть в мою учетную запись Twitter с URL https://twitter.com/joelbyler

Я не согласен с выходом из системы, требующей POST. Как часть вашего API, если вы собираетесь поддерживать сеанс, тогда идентификатор сеанса в форме UUID может быть тем, что можно использовать для отслеживания пользователя и подтверждения того, что действие, которое принято, разрешено. Тогда даже GET может передать идентификатор сеанса на ресурс.

Короче говоря, я бы порекомендовал вам сохранить его простым, URL-адрес должен быть незабываемым.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню