Як реалізувати логін у веб-службі RESTful?


78

Я створюю веб-додаток із рівнем послуг. Рівень послуг буде побудований з використанням дизайну RESTful. Думається, що в майбутньому ми можемо створювати інші додатки (iPhone, Android тощо), які використовують той самий рівень послуг, що і веб-додаток. Моє запитання полягає в наступному - як мені застосувати логін? Я думаю, у мене виникають проблеми з переходом від більш традиційного дієслівного дизайну до дизайну, заснованого на ресурсах. Якби я будував це за допомогою SOAP, я, мабуть, мав би метод під назвою Login. У REST у мене повинен бути ресурс. У мене виникають труднощі з розумінням того, як слід створити свій URI для входу. Це має бути приблизно так:

http: // myservice / {ім'я користувача}? p = {пароль}

РЕДАГУВАТИ: Веб-програма інтерфейсу використовує традиційну платформу ASP.NET для автентифікації. Однак у певний момент процесу автентифікації мені потрібно перевірити надані облікові дані. У традиційному веб-додатку я б шукав базу даних. Але в цьому сценарії я закликаю службу замість того, щоб шукати базу даних. Тож мені потрібно щось у службі, що перевірить надані облікові дані. І на додаток до перевірки наданих облікових даних мені, мабуть, також потрібна якась інформація про користувача після успішної автентифікації - такі речі, як їх повне ім'я, їх ідентифікатор тощо. Сподіваюсь, це робить питання більш зрозумілим.

Або я не думаю про це правильно? Я відчуваю, що мені важко описати своє запитання правильно.

Корі

Відповіді:


62

Як вже зазначав С.Лотт, у нас тут є дві складені речі: Вхід та автентифікація

Тут автентифікація поза сферою застосування, оскільки це широко обговорюється і існує спільна згода. Однак, що нам насправді потрібно, щоб клієнт успішно пройшов аутентифікацію проти веб-служби RESTful? Правильно, якийсь маркер, назвемо його маркером доступу.

Клієнт) Отже, все, що мені потрібно, - це маркер доступу, але як отримати такий RESTfully?
Чому б просто не створити його?
Клієнт) Як це?
Сервер) Для мене маркер доступу - це не що інше, як ресурс. Таким чином, я створу його для вас в обмін на ваше ім’я користувача та пароль.

Таким чином, сервер може запропонувати URL-адресу ресурсу "/ accesstokens", для розміщення імені користувача та пароля, повертаючи посилання на новостворений ресурс "/ accesstokens / {accesstoken}". Крім того, ви повертаєте документ, що містить маркер доступу та href із посиланням на ресурс:

<маркер доступу
  id = "{сюди йде ідентифікатор маркера доступу; наприклад, GUID}"
  href = "/ accesstokens / {id}"
/>

Швидше за все, ви насправді не створюєте маркер доступу як підресурс і, отже, не будете включати його href у відповідь.
Однак якщо ви це зробите, клієнт може створити посилання від свого імені чи ні? Ні!
Пам'ятайте, справді RESTful веб-служби пов'язують ресурси між собою таким чином, щоб клієнт міг самостійно орієнтуватися без необхідності генерувати будь-які посилання на ресурси.

Останнє запитання, яке у вас, мабуть, полягає в тому, чи потрібно розміщувати ім’я користувача та пароль як HTML-форму або як документ, наприклад, XML або JSON - це залежить ... :-)


4
Не ідеально слідуючи REST, але простий і помітно кращий за інших. Плюс поділився з хорошим гумором.
Тед Джонсон,

2
Патріку, ти пропонуєш те саме, що і цю відповідь? stackoverflow.com/a/1135995/14731
Гілі

Чи правильний код стану 403, коли ім’я користувача та / або пароль не збігаються?
tsobe

Яка ідея. Створення ресурсу "accesstoken".
Сортер

25

Ви не "входите". Ви "аутентифікуєтесь". Світ різниці.

У вас є багато варіантів автентифікації.

HTTP Basic, Digest, NTLM та AWS S3

  • HTTP Basic і Digest аутентифікація. Тут використовується HTTP_AUTHORIZATIONзаголовок. Це дуже приємно, дуже просто. Але це може призвести до великого трафіку.

  • Аутентифікація імені користувача / підпису. Іноді називають автентифікацією "ID та KEY". Для цього можна використовувати рядок запиту.

    ?username=this&signature=some-big-hex-digest

    Саме цим користуються такі місця, як Amazon. Ім'я користувача - "id". "Ключ" - дайджест, схожий на той, що використовується для аутентифікації HTTP Digest. Обидві сторони повинні домовитись про дайджест, щоб продовжити.

  • Якась автентифікація на основі файлів cookie. Наприклад , OpenAM можна налаштувати як агент для автентифікації та надання файлів cookie, які потім може використовувати ваш веб-сервер RESTful. Клієнт спочатку автентифікується, а потім надає файли cookie з кожним запитом RESTful.


2
@ S.Lott @Corey Користувачі абсолютно можуть взаємодіяти з системами RESTful. Більшість статичних веб-сайтів у форматі HTML - це "послуги".
Даррел Міллер

7
@ Даррел Міллер: "Ваша ідея ... помилкова" не забезпечує належного контексту або чогось корисного. Це щось негативне і не надто корисне.
S.Lott

5
@ Даррел Міллер: "заява REST обмежена ... просто смішним". Як би там не було. Замість того, щоб повторити те, що не так, чи могли б ви пояснити, що правильно? Чи не могли б ви надати просте позитивне твердження замість негативного? Не могли б ви пояснити, що таке REST замість того, що це ні? Існує нескінченна кількість речей, якими це не є.
S.Lott

4
@ Даррел Міллер: 5.2.1.2 Уявлення здаються досить чіткими. Ваші коментарі дуже негативні. Чи не могли б ви надати позитивні виправлення чи оновлення замість негативу? Я не можу зрозуміти, як виправити чи змінити свою відповідь, щоб задовольнити вас, оскільки все, що ви робите, - це сказати, що я якось «недосконалий», «поширюю неправильну інформацію» або «смішно». Що є менш вадким, менш неправильним чи менш смішним?
S.Lott

5
@ S.Lott 1) ​​Користувачі постійно взаємодіють із системами RESTful. 2) HTML - цілком дійсний тип носія для повернення системи RESTful. 3) REST не є підмножиною HTTP. REST - це архітектурний стиль, HTTP - протокол. 4) Системи RESTful не обмежуються "веб-сервісами". 5) Системи RESTful можуть імітувати логін, використовуючи якусь форму маркера авторизації, не зазнаючи проблем, пов'язаних із сеансами.
Даррел Міллер

1

Чудове питання, добре поставлене. Мені дуже подобається відповідь Патріка. Я використовую щось на зразок

- / users / {ім'я користувача} / loginsession

З POST і GET обробляються. Тож я публікую новий сеанс входу з обліковими даними, а потім можу переглядати поточний сеанс як ресурс за допомогою GET.

Ресурс - це сеанс входу, який може мати маркер доступу або код автентифікації, термін дії тощо.

Як не дивно, але мій абонент MVC повинен сам представити маркер ключа / носія через заголовок, щоб довести, що він має право спробувати створити нові сеанси входу, оскільки сайт MVC є клієнтом API.

Редагувати

Думаю, деякі інші відповіді та коментарі тут вирішують проблему загальнодоступною таємницею, що не входить до групи, і просто підтверджують автентичність за допомогою заголовка. Це чудово в багатьох ситуаціях або для дзвінків між послугами.

Іншим рішенням є передача маркера, OAuth або JWT, або іншим способом, що означає, що "вхід" вже відбувся за допомогою іншого процесу, можливо, звичайного користувацького інтерфейсу для входу в браузері, який базується на формі POST.

Моя відповідь стосується служби, яка стоїть за цим інтерфейсом, припускаючи, що ви хочете, щоб логін та автентифікація та управління користувачами були розміщені в службі REST, а не в коді MVC сайту. Це ІМІ послуга входу користувачів.

Це також дозволяє іншим службам "увійти" та отримати термін дії, який закінчується, замість використання загальнодоступного ключа, а також тестових скриптів в інтерфейсі клієнта або поштарці.


2
Передайте маркер у заголовок, так. Передайте його як частину URL-адреси, ні. URL-адреса зашифрована під час передачі, коли ви використовуєте HTTPS. Однак; URL-адреса також зберігається в історії браузера та в журналах сервера. Існує маса вагомих причин, щоб уникнути передачі даних, що охоплюють безпеку, у параметрах запиту URL.
Крейг,

0

Оскільки з 2011 року трохи змінилося ...

Якщо ви відкриті для використання сторонніх інструментів і трохи відхиляєтесь від REST для веб-інтерфейсу, розгляньте http://shiro.apache.org .

Shiro в основному надає вам фільтр сервлетів, призначений для автентифікації, а також авторизації. Ви можете використовувати всі методи входу, перелічені @ S.Lott, включаючи просту автентифікацію на основі форми.

Відфільтруйте інші URL-адреси, які вимагають автентифікації, і все зробить Shiro.

В даний час я використовую це у своєму власному проекті, і дотепер він працював у мене досить добре.

Ось ще щось, що може зацікавити людей. Https://github.com/PE-INTERNATIONAL/shiro-jersey#readme


0

Перше, що слід зрозуміти про REST, це те, що доступ до ресурсу базується на токені. На відміну від традиційних способів, доступ надається на основі перевірки маркера. Простими словами, якщо у вас є правильний маркер, ви можете отримати доступ до ресурсів. Зараз є багато інших речей для створення і маніпулювання маркерами.

Для першого запитання ви можете розробити Restfull API. Повноваження (ім’я користувача та пароль) будуть передані на ваш сервісний рівень. Потім сервісний рівень перевіряє ці облікові дані та надає маркер. Сертифікати SSL використовують протокол OAUTH і є більш безпечними.

Ви можете оформити свій URI таким чином - URI для запиту маркера- > http: // myservice / some-directory / token ? (Ви можете передати ідентифікаційні дані в цьому URI для маркера)

Щоб використовувати цей маркер для доступу до ресурсу, ви можете додати цей [Authorization: Bearer (token)] до вашого заголовка http.

Цей маркер може бути використаний клієнтом для доступу до різних компонентів рівня обслуговування. Ви також можете змінити термін дії цього маркера, щоб запобігти неправильному використанню.

Що стосується вашого другого запитання, одне, що ви можете зробити, - це надати різний маркер для доступу до різних компонентів ресурсу вашого сервісного рівня. Для цього ви можете вказати параметр ресурсу у своєму маркері та великий дозвіл на основі цього поля.

Ви також можете перейти за цими посиланнями для отримання додаткової інформації - http://www.codeproject.com/Articles/687647/Detailed-Tutorial-for-Building-ASP-NET-WebAPI-REST

http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api


-4

Я стикався з тією ж проблемою раніше. Вхід не найкраще перекладається на дизайн на основі ресурсів.

Зазвичай я обробляю це, маючи ресурс Login та передаючи ім’я користувача та пароль у рядок параметрів, що в основному робить

ОТРИМАТИСЯ на http: // myservice / login? U = {ім'я користувача} & p = {пароль}

Відповідь - це якийсь рядок сеансу або автентифікації, який потім можна передати іншим API для перевірки.

Альтернативою GET на ресурсі входу є POST, REST пуристи, мабуть, мені зараз не сподобаються :), і передача кредитів у тілі. Відповідь буде такою ж.


11
Пароль? Звичайний текстовий пароль? Як рядок запиту? Ви насправді це мали на увазі, або ви маєте на увазі дайджест пароля?
S.Lott

Дякую. Що має сенс. Ось наступне запитання - для великої програми ви б створили одну велику службу RESTful для всього або розбили речі на різні служби? Я думав про те, щоб мати послугу лише для автентифікації, а потім різні служби для різних модулів моєї програми. Чи є причини, чому ви робили б чи не робили це так чи інакше?
Кори Бернетт

3
С. Лотт: Це залежить від того, що ви намагаєтесь зробити. Звичайно, якщо ви можете зробити дайджест, то неодмінно. Іноді дайджест неможливий. Якщо єдина можливість відкрита для вас - це надсилання пароля у вигляді простого тексту, будь ласка, виконайте це через SSL, у цьому випадку також краще використовувати POST, а не GET, щоб браузер не пам’ятав про те, що ви надіслали.
Олексій

Кори: Я не впевнений, що розумію різницю між однією великою веб-службою та багатьма різними. Зазвичай ви визначаєте свою послугу з точки зору ресурсів, додаючи лише стільки, скільки має сенсу. Я думаю, що я втрачаю вашу думку.
Олексій

Алекс: припустимо, у мене було 4 різних основні розділи мого веб-додатку - звіти, замовлення, завантаження та рахунки-фактури. Чи мало б сенс мати 4 різні визначення послуг або лише 1 визначення послуг? Чи є якісь конкретні причини, чому ви не хотіли б розбивати речі на безліч різних служб?
Корі Бернетт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.