RESTful дизайн / вход или регистрация ресурсов? - PullRequest
105 голосов
/ 21 августа 2011

Я разрабатывал веб-приложение и затем задумался о том, как мой 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, но я был бы очень признателен за некоторые рекомендации относительно того, что я изложил здесь, если это возможно.

Спасибо!

ОБНОВЛЕНИЕ:

Я также хотел бы высказать несколько мнений по поводу:

/user/1

против

/user/myUserName

Ответы [ 6 ]

105 голосов
/ 31 августа 2011

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 против /users/joe) обычно обусловлено желанием быть более дружелюбным к пользователям или поисковым системам, а не какими-либо техническими требованиями.Либо хорошо, но я бы порекомендовал вам быть последовательным.

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

55 голосов
/ 30 августа 2011

Особо выделяется одна вещь, которая не соответствует REST: использование 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-адреса?" это рассмотрение в двух областях:

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

Если JRandomUser хочет посмотреть его собственный профиль, и вы хотите, чтобы URL был красивее, чем foo.com/user/JRandomUser или foo.com/user/(JRandom's 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.
                     */

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

  1. Потребитель: какие ресурсы предназначены для просмотра непосредственно в браузере, загрузки через XHR или доступа к какому-либо другому виду клиента?
  2. Доступ / личность: зависит ли ответ от файлов cookie или ссылок?
49 голосов
/ 31 августа 2011

Сессии не RESTful

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

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

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

  • Обычно я использую обычную аутентификацию или не аутентифицируюсь со службами REST.

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

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

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

20 голосов
/ 30 августа 2011

Я собираюсь просто рассказать о своем опыте интеграции различных веб-служб 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 голосов
/ 21 июля 2017

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

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

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

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

2 голосов
/ 29 августа 2011

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

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

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

...