Как стать автором
Обновить

Комментарии 101

Вот это отсутствие стандартизации на контракт севиса, очень напрягает. То есть вы должны еще убедить всех людей, почему не нужен SOAP и ак быть в случае выставления рест-сервиса кому-нибудь.
По пункту 3 сравнения — а что не устраивает?
я защищаю SOAP в том пункте. Говорю, что например в .Net сложность разработки сопоставимая.
18 ноября и 27 октября :) Равенство у вас какое то необыкновенное :)
Я округлил :)

Можно было написать — «два года назад, так же под конец осени, когда уже чувствуется дуновение приближающейся зимы, воздух в облетевших кронах деревьев прозрачен и зво́нок, но нет еще той промозглости, нагоняющей депрессию на утонченное сознание программиста и писателя, меня посетила гениальная мысль касательно веб-сервисов» :))
Мы много хорошего потеряли из-за таких ваших округлений, похоже.
очень неплохая статья, рекомендую
Все-таки очень бы хотелось увидеть ответ на вопрос
”А как вообще возможна аутентификация в архитектуре REST, если читателю на протяжении всей этой статьи внушалось, что RESTful сервис должен быть stateless?”
Cookies или https.
НЛО прилетело и опубликовало эту надпись здесь
>> HTTPS только с шифрованием поможет.

Правда?
Например — www.opennet.ru/base/sec/ssl_cert.txt.html

>> Cookies нарушает принцип Stateless — серверу надо хранить связь этого Cookies с конкретным пользователям.

Совсем необязательно, куки (а точнее авторизационный токен) уже может нести в себе всю информацию о сессии и пользователе.
НЛО прилетело и опубликовало эту надпись здесь
Давайте определимся все-таки. Есть аутентификация — выдача пользователю некоего токена-пропуска, на основе его логина и пароля.
Авторизация — определение пользователя на основе токена и обеспечение доступа к некоторым запрошенным ресурсам.

Отличается это тем, что токен может нести в себе некоторые дополнительные данные, которые можно проверить и по которым можно определеить пользователя БЕЗ обращения к каким-либо базам данных.
Еще один плюс — у вам может быть несколько механизмов аутентификации (своя БД, аутентификация через всякие openauth, внешние сервисы и тому подобное), но единая авторизация за счет единого авторизационного токена. Ну или единый сервис аутентификации, который выдает токен и набор разных сервисов, которые этот токен принимают.
НЛО прилетело и опубликовало эту надпись здесь
1. БД — это внешний ресурс, и состояние БД — это не есть состояние самого сервиса.
Сервисы с состоянием — это например сервисы в виде конечных автоматов (workflow services), которые ожидают вызовов от пользователя в строго определенном порядке и в зависимости от передаваемых данных

msdn.microsoft.com/en-us/magazine/cc164251.aspx

2. Есть целый стандартизованный формат для токенов (правда больше для soap) — en.wikipedia.org/wiki/Security_Assertion_Markup_Language

Соответственно, и примеры там есть ;)
НЛО прилетело и опубликовало эту надпись здесь
1) Ну смотрите:
Я делаю GET somehost/someresource/100500
Далее кто-то делает POST somehost/someresource/100500 и изменяет ресурс который лежит по данному uri.
Когда я сделают такой же GET somehost/someresource/100500 я получу уже совсем другой результат. Это же не значит, что сервис уже не RESТ? А все потому что изменилось не состояние сервиса, а состояние некоего внешнего по отношению к сервису ресурса.
А поведение осталось то же — берем ресурс из БД, сериализуем и возвращаем пользователю.

А вот пример сервиса с воркфлоу: например у меня есть некий документооборот и я хочу создать некий ресурс-запись и привязать к нему некий набор файлов. С воркфлоу-сервисом возможен следующий вариант:
1. Я вызываю у сервиса некий метод «Создай мне ресурс», сервис его создает и запоминает состояние для моей сессии, что я только что просил у него создать ресурс и запоминает например некий внутренний идентификатор.
2. Несколькими последовательными запросами я заливаю файлы, причем сервис привязывает их к той записи, которую только что для меня создал.

Сценарий для типичной веб-разработки странный, но довольно-таки часто встречается в энтерпрайзном документообороте, что и породило разнообразные state machine движки.
Обратите внимание, что сервис по сути поменял интерфейс между шагом 1 и 2, как и положено конечному автомату.

2) Простой пример — токен может сразу нести в себе информацию о том, какими правами обладает пользователь или к какому множеству данных он может получить доступ, что позволяет их проверить без лишних запросов к той же БД. Так например работает Active Directory, что спасает в сильно распределенных системах.
НЛО прилетело и опубликовало эту надпись здесь
> и который нельзя подделать
токены обычно подписывают своим ключем
1. Все правильно, кроме того, что не все стейтлесс сервисы — обязательно REST.
НЛО прилетело и опубликовало эту надпись здесь
Ок ;)
2. Именно подпись с открытым и закрытым ключами.
НЛО прилетело и опубликовало эту надпись здесь
Кроме дополнительной информации токен отличается тем, что не несет как правило «закрытой» информации (пароля того же), что повышает секьюрность.

За многословность прошу прощения, не сразу понял в чем у вас недопонимание.
«Из этого следует вывод: аутентификацию в REST можно делать как угодно, лишь бы для это был отдельный URL.»

А как же HTTP BAsic Authentication?
НЛО прилетело и опубликовало эту надпись здесь
1) Ну смотрите:
Я делаю GET somehost/someresource/100500
Далее кто-то делает POST somehost/someresource/100500 и изменяет ресурс который лежит по данному uri.
Когда я сделают такой же GET somehost/someresource/100500 я получу уже совсем другой результат. Это же не значит, что сервис уже не RESТ?

откаменчу, что до этого мы предполагали, что сам ресурс, вокруг которых весь REST крутится, НЕ ИЗМЕНЯЕТСЯ пока мы там аутентифицируемся или еще что-то
> откаменчу, что до этого мы предполагали, что сам ресурс, вокруг которых весь REST
> крутится, НЕ ИЗМЕНЯЕТСЯ пока мы там аутентифицируемся или еще что-то

Т. е. блокируется что ли? А если у нас хайлоад какой-нибудь? Неее, не складывается что-то.
нет-нет, просто для упрощения рассуждений мы предполагали что ресурс не изменяется. А потом вроде как ввели новую переменную в рассуждения. Но суть от этого не меняется совершенно.
Просто надо понимать, что есть:
1. Входные данные
2. Некие бизнес-данные
3. Некие данные о состоянии самого сервиса.

И пока данных о состоянии сервиса нет и они не влияют на его поведение — сервис остается stateless.

Грубо говоря:
Если сервис возвращает, например, список пользователей, но после 100-го запроса внезапно переключает некий флаг и начинает возвращать список пользователей с каким-нибудь фильтром или вообще какой-нибудь другой список — то это stateful service.
Если же он всегда возвращает список пользователей, но при этом кол-во пользователей в системе меняется и результат запроса естественно тоже меняется, то это не мешает сервису быть stateless.
все верно.

давайте считать тот мой камент отсутвующим, он оказался запутывающим, а не уточняющим.
Ок ;)
И если при одинаковых входящих параметрах результат работы сервиса будет отличаться — это уже не REST.

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

Логин-пароль или токен при этом не считаем входными данными.
> И если при одинаковых входящих параметрах результат работы сервиса будет отличаться — это уже не REST.
> В теории очень правильно.

Т.е. любой сервис, который возвращает мне результат некоего запроса к БД, которая может изменяться — это уже stateful-сервис?

> Логин-пароль или токен при этом не считаем входными данными.

А чем мы их считаем?
пропуском, можно сказать.

Вывод функции от них не может изменяться, он может только отсутствовать, если прав нет.
Ок.
Пример из коммента выше со списком пользователей системы:
Юзер Вася директор филиала и может видеть только пользователей своего филиала.
Юзер Дима админ всея системы и всегда видит всех пользователей системы.

В итоге, сервис один, он все равно stateless, но вывод функции зависит от того какой пользователь делает запрос.
«Ок.
Пример из коммента выше со списком пользователей системы:
Юзер Вася директор филиала и может видеть только пользователей своего филиала.
Юзер Дима админ всея системы и всегда видит всех пользователей системы.

В итоге, сервис один, он все равно stateless, но вывод функции зависит от того какой пользователь делает запрос. „

такое поведение функции мне кажется REST-неправильным и вот почему:

директор Вася и Админ Дима должны использовать разные функции, а именно директор ex.com/users?department=34, админ — ex.com/users.
Соответственно прав директора не хватит на вторую функцию, он в ответ на ее вызов ничего не получит.
Вопрос на самом деле очень интересный. Прошу небольшой перерыв для того чтобы порыться в книжках ;)
После обсуждения с коллегами и вкуривания в «SOA Designs Patterns» Томаса Эрла пришли к такому выводу:
То что авторизационный токен передается отдельно от других входящих параметров, не означает, что токен не входит в множество входящих параметров. Бизнес-логика сервиса естественно может зависеть от параметров, в том числе и от параметра «залогинившийся пользователь».
Соответственно, мой вариант сервиса вполне имеет право на существование, а ваш — все-таки решает немножко другую задачу (у вас два запроса — один на получение всех пользователей, второй — на получение пользователей конкретного отдела).
Мне кажется, что «Бизнес-логика сервиса естественно может зависеть от параметров, в том числе и от параметра «залогинившийся пользователь».» — это нарушение принципа stateless…
Это означает, что вы неправильно понимаете, что означает stateless.
Смотрите, пусть есть некий черный ящик со входами и выходами, причем входами являются: входные данные, которые передает пользователь и некие бизнес-данные из внешних по отношению к сервису источников (база данных). Выходными данными является результат некоей обработки входов.
Тогда:
stateless-сервис будет всегда выводить на выход одни и то же значения при одних и тех же значения на входах
statefull-сервис имеет некую внутреннюю память (состояние) и выход зависит не только от текущих значений входа, но и от того что было на входах ранее.

Почитайте про конечные автоматы, понятнее будет ;)
да, теперь соглашусь, разъяснение помогло.

Меня смущало то, что я не понимал, как кешировать вывод в примере с одной функцией для админа и директора, теперь додумался, можно же добавить что-то varyByParam и кешировать отдельно для юзеров с разным набором прав.

Спасибо вам и вашим коллегам ;)
Не за что, рады помочь.
Сама логика внутри сервиса может быть сколь угодно сложной, главное чтобы она не учитывала «историю жизни сервиса».
3 пункта — отличное обобщение!

По поводу сторонней БД, надо подумать, а не сломает ли нам эта штука кеширование…
Предыдущее было на
«1. Вся аутентификация на уровне HTTP/HTTPS и нижележащих протоколов (PPPoE какой-нибудь например) удовлетворяет REST идеологии (другой вопрос, как проводить авторизацию, т.е. передавать в сервис информацию о текущем пользователе, полученную уровнем ниже).
2. Аутентификация и авторизация в одном флаконе (логин/пароль в каждом запросе) также удовлетворяет REST.
3. Аутентификация и авторизация в разных запросах — не REST. Как минимум та часть, которая аутентификацией занимается уже не REST.!»

и «И немного в сторону. Есть сервис, который заводит пользователю сессию, записывает ее id в Cookie и при каждом пользовательском запросе проверяет в базе, есть ли там такая сессия. Это не REST, он хранит состояние. А другой сервис использует аутентификацию через сторонний сервис и при каждом пользовательском запросе уточняет у стороннего сервиса, валидный ли пользователь. Вроде бы REST, т.к. наш сервис состояний не хранит. И вот непонятно, по какому критерию собственная БД еще является хранением состояния, а сторонний сервис — уже нет. Фактически разработчик может сказать «У меня REST приложение. А БД — это внешний ресурс, это уже не REST». И никто ему в этом не помешает. Этот момент кажется мне очень спорным.»
имеется ввиду, что каждому клиенту генерится личный сертификат
пользователи с отозванным сертификата или без него не могут работать с сервом, и получают ошибку доступ запрещен
Видимо statless не нужно понимать буквально. Достаточно лишь того, что бы состояние не хранилось в памяти конкретного сервера. Если сессии хранить в централизованной БД, то это вполне себе stateless.
Вы хотите сказать что все REST сервисы в интернете с кукисами — не REST сервисы?
НЛО прилетело и опубликовало эту надпись здесь
ок, поправлюсь:
все REST сервисы в интернете с авторизацией с использованием кукисов/заголовков — не REST сервисы?
НЛО прилетело и опубликовало эту надпись здесь
«О том, что нельзя использовать Cookie в REST архитектуре я ничего не говорил. Только о том, что их нельзя использовать для авторизации. „

Почему? А если сценарий как описан тут?
нет
нет было ответом на «Вы хотите сказать что все REST сервисы в интернете с кукисами — не REST сервисы? „
Да хоть Basic :)
Авторизация — часть запроса, ничего за его пределами не хранится.
В каждом сообщении передают юзера и пароль.
А очень просто. Сначала выполняем аутентификацию. При успешном входе, клиенту возвращаеться специально сгенерированный токен по которому могут идентифицировать клиента на сервере. Далее при каждом запросе к REST сервису, добавляется дополнительный заголовок «Authorization» в котором вы указываете тип авторизации и полученый токен.

GET www.google.com/cse/api/default/cse/
Authorization: GoogleLogin auth=IM6F7Cx2fo0TAiwlhNVdSE8Ov8hw6aHV
НЛО прилетело и опубликовало эту надпись здесь
Почему отсутствует stateless?

Клиент делает запрос, к примеру:
POST service.com/token/ передаешь ему логин пароль, сервис производит аутентификацию и в ответ отдает тебе токен. Токен хранится в базе и имеет разрешение/запреты на определенные действия.

Дальше клиент делает те запросы которые ему нужны и в заголовке передает токен:
GET service.com/car/1
PUT service.com/car/1 и т.д.

В итоге получается, что сервис не хранит твое состояние, ты создал новый ресурс, а потом просто запрашиваешь или изменяешь другие.

Или я что-то путаю?)
НЛО прилетело и опубликовало эту надпись здесь
Т.е. получается, что мой вариант имеет место быть в REST архитектуре?
НЛО прилетело и опубликовало эту надпись здесь
Спасибо :)
Добавлю, что вариант с куки все-таки удобнее, если клиент работает из браузера. ИМХО, конечно.
Вообще-то это ничем не отличается от использования кук :)
Authorization — стандартизированный заголовок HTTP, он ближе к голому HTTP и соответственно больше соответствует идеологии REST.
Куки — это просто хедер, он не ближе и не дальше. Так же как и хедер авторизации. Можно еще query param добавлять, видел и такое решение. Это все го лишь детали реализации. Важно, что сессия у вас есть в любой из реализаций и это не делает какую-либо реализацию ближе или дальше от HTTP.
Вопрос не в реализации, а в семантике. Если есть стандартизованный хидер, предназначенный специально для авторизационных токенов, то токены там и должны лежать в большинстве случаев.

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

Дык нет разницы в семантике. А сематника такова: передать (все равно как) токен, по этому токену идентифицировать сессию на сервере и выполнить запрос в контексте этой сессии. Но как раз вижу разницу в реализации.

>потому что это ближе к стандарту,

HTTP State Managend aka Cookie тоже очень и очень распространенный стандарт. Оба решения одинаковы, как по семантике, так и по стоимости поддержки.
Не согласен по поводу семантики.

Хидер Authorization введен специально для авторизации (RFC 2617).
Cookie — это механизм хранения информации о состоянии сессии (RFC 6265).

Лично мне разница очевидна.
Передача и обработка авторизационного токена через Authorization хедер есть частный случай реализации сессионного механизма. Куки — более общее решение.
На всякий случай — ru.wikipedia.org/wiki/%D0%A1%D0%B5%D0%BC%D0%B0%D0%BD%D1%82%D0%B8%D0%BA%D0%B0

То что вы называете семантикой — это не семантика (смысловое значение, грубо говоря), а описание процесса.
Грамотный подход! Очень удобно в различных средах пользовать!
А как вообще возможна аутентификация в архитектуре REST, если читателю на протяжении всей этой статьи внушалось, что RESTful сервис должен быть stateless?



<hr />
Цитата из педивикии:
Аутентифика́ция (англ. Authentication) — проверка принадлежности субъекту доступа предъявленного им идентификатора; подтверждение подлинности.[1]
Аутентификацию не следует путать с идентификацией и авторизацией[2].


Т.е. вопрос задан некорректно. Если не допускается хранения состояний то пароль/логин должны передаваться в каждом запросе, что логично. В этом и есть смысл stateless — всё необходимое для выполнения запроса (в том числе логин/пароль) передаётся каждый раз в каждом запросе.

REST предлагает не мудрить а использовать те средства которые есть в веб с начала времён. Для настройки прав доступа к каждому ресурсу можно использовать стандартные средства веб-сервера, для защиты трафика можно использовать стандартный HTTPS.

REST предлагает не плодить новые сущности а использовать то что уже давно прекрасно работает. Например для обозначения действия с ресурсом предлагается использовать указание типа запроса (POST, PUT, GET и т.п.) — но именно для этого типы запросов и были придуманы когда зарождался интернет.

другой пример — если ресурса нет то клиент полоучает стандартную 404 ошибку а не исключение или ещё что-то. Если нет доступа к ресурсу то, соответственно, ошибку 403.
>А как вообще возможна аутентификация в архитектуре REST, если читателю на протяжении всей этой статьи внушалось, что RESTful сервис должен быть stateless?

<hr />
Цитата из педивикии:
Аутентифика́ция (англ. Authentication) — проверка принадлежности субъекту доступа предъявленного им идентификатора; подтверждение подлинности.[1]
Аутентификацию не следует путать с идентификацией и авторизацией[2].

Т.е. вопрос задан некорректно

Он был задан для того, чтобы заставить читателей задуматься.
спасибо всем, кто помог ответить на вопрос.
Как настоящий зануда позволю себе заявить что автор статьи сравнивает протокол с парадигмой построения архитектуры веб серверов. Правильно было бы сравнивать RPC и REST, или SOAP и HTTP.
А по сути я так и не «почувствовал разницу», потому что в статье рассказывается в основном только про REST, а про SOAP пару упоминаний.

От себя могу сказать что RPC с одной стороны удобнее чем REST за счет того что он предоставляет WSDL, описывающий все возможности веб сервиса и позволяющий сгенерировать готовый код. RPC сервис обычно используют для реализации работы десктопных/консолных клиент серверных приложений.
С другой стороны REST сервис более прост в реализации и использовании именно для веб разработки.
позволю себе заявить что автор статьи сравнивает протокол с парадигмой построения архитектуры

Он как раз не сравнивает, а подчеркивает, что сравниваются разные вещи, что не правильно.
> позволю себе заявить что автор статьи сравнивает протокол с парадигмой построения архитектуры
Он как раз не сравнивает, а подчеркивает, что сравниваются разные вещи, что не правильно.

И первое и второе утверждение абсолютно верны.
>От себя могу сказать что RPC с одной стороны удобнее чем REST за счет того что он предоставляет WSDL,

Не-не, WSDL не является необходимым компонентом для RPC. Это как раз из протокола SOAP
SOAP — это не RPC. Точнее, есть SOAP 1.1 и SOAP 1.2. Первый — это ещё можно назвать RPC, а вот второй уже скорее с SMTP можно сравнивать, так как это протокол передачи сообщений, а не вызова удалённых процедур. Ну и если упоминать WSDL — то вообще RESTful и SOAP сравнивать нельзя.
SOAP и HTTP сравнивать вообще невозможно, это сравнение между эскалатором и пассажирами не нём.
Сделать WSDL для REST особых проблем не представляет, только стоит ли — получится SOAP.
>SOAP и HTTP сравнивать вообще невозможно, это сравнение между эскалатором и пассажирами не нём

Супер!
картинки не грузятся, перенесите пожалуйста например на habrastorage.org
> картинки не грузятся, перенесите пожалуйста например на habrastorage.org

у кого-нибудь еще есть такая проблема?

Камент от меня разработчикам Хабра: «Обязательно нужно добавить в HTML-редактор фунцкий вставки изображения c локального диска!»
"«REST vs SOAP» можно перефразировать в «Простота vs Стандарты»"
Я бы перефразировал на «Простота vs Избыточность», т.к. «Стандарты» — как мне кажется, применимы с какой-то долей к обоим с рамках соглашений.
Ох. Неужели этот выбор прям настолько важен, что определяет успех или неудачу продукта, и выбрав одно, изменить в будущем это будет очень сложно? Очевидно что нет. На успех/провал продукта это никак не влияет, а современный уровень развития технологий позволяет нам менять одно на другое без заметных усилий (естественно при условии, что мы помним про инкапсуляцию и SRP и стараемся их придерживаться). Тогда какая разница? Зачем писать об этом статьи
Забавно) Кому-то этот выбор, похоже, кажется решающим, судя по минусам)
а при чем здесь успех или неудача? здесь технологии обсуждаются.
Не надо выбирать. Берете Axis2, пишете Java класс, объявляете его как сервис.
После этого вы можете его вызывать как SOAP сервис и используя REST в т.ч. получая ответ в JSON представлении.

Хотя SOAP это более полная функциональность, ведь еще есть

— SAAJ/MTOM (пересылка эффективно бинарников, без кэширования в RAM)
— XML-Signature (подписывание тела вызова сервиса)
— XML Payload (возможность передать любой XML)
Напишите как-нибудь статью с примерами о том, как можно вызывать Axis2 сервис через REST? А то на официальном сайте Axis2 информации совсем мало по этому поводу. В частности, как передавать параметры — не совсем ясно.
1. Все через POST по HTTPS делать…
2. В теле запроса передавать TokenId + все остальные поля
3 .com/(get|post|update|delete)/car/(id)
Ну послушайте, опять статья про REST в которой нет ни одного упоминания гипертекста или HATEOAS (Кусок про «Link things together» засчитать за оные невозможно).

Как раз для таких случаев Рой Филдинг и отрезал раз и навсегда: Если изменение состояния приложения не продиктовано гипертекстом — оно не может считаться RESTful.

Это как бы и есть ключевое отличие REST (та самая суть, которую автор не уловил). Ссылки и их отношения вместо захардкоденых URI, медиа-типы и их описания вместо «описания форматов по заданным URI» — это про REST.

Модель работы браузер — сервер и есть модель RESTful приложения. Клиент (браузер) знает только протокол взаимодействия (http), умеет интерпретировать медиа-тип (html).

В умение интерпретировать медиа-тип включается и то, как интерпретировать встречающиеся в нем URI, как понимать их взаимоотношения. Например, один и тот же URL в тэгах «img», «a», «link» и «form method=post» интерпретируется по-разному, обеспечивая разные изменения состояния приложения.

Но в этом и есть основная проблема при реализации REST API в данный момент. Общепризнанных гипермедиа-типов очень мало (text/html, application/atom+xml) и использовать их можно далеко не для каждой задачи. А описывать собственный… это уже совсем не просто.
Спасибо, очень ценное замечание. Я действительно рассматривал это в другом контексте
Добавлю еще общую штуку про аутентификацию для тех, у кого до сих пор не появилось четкого понимания, что она не нарушает принципы REST и что все в порядке =)

1. В общем делаем мы запрос GET example.com/cars.
2. Сервер смотрит — анонимный юзер, нельзя давать список машин
3. Перенаправляет нас на сервер аутентификации
4. мы там вводим имя-пароль
5. Сервер проверяет данные и ставит нам куку
6. Нас обратно перенаправляют на example.com/cars
7. REST-сервис видит куку, проверяет ее и возвращает список машин. Самое важное, что это совершенно не является нарушением принципов REST. Мысля, как ASP.NET разработчик, эта проверка токена происходит в httpModule, т.е. то, что мы могли бы как-то назвать состоянием, не имеет ничего общего с собственно обработкой запроса — проверка происходит еще до попадания в функцию ответа на GET запрос.
С кешированием тоже все ок — кешируется ведь результат работы той функции обработки GET запроса.

Задачи 2 и 3 прям так и шепчут «Реализуй нас, покупатели найдутся!».
«Для начала я бы назвал простоту основным преимуществом архитектуры REST». Может в этом смысл аббревиатуры? Расшифровка не слишком отражает идею, а вот сокращение REST — вполне. Just rest и не заморачивайся о статусах, just rest и используй стандартные методы HTTP
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории