Пароль RESTful reset

Каков правильный способ структурирования ресурса RESTful для сброса пароля?

Этот ресурс предназначен для сброса пароля для тех, кто потерял или забыл свой пароль. Это аннулирует старый пароль и отправляет им по электронной почте пароль.

Два варианта, которые у меня есть:

POST /reset_password/{user_name}

или...

POST /reset_password
   -Username passed through request body

Я уверен, что запрос должен быть POST. Я менее уверен, что выбрал подходящее имя. И я не уверен, что имя пользователя должно быть передано через URL-адрес или тело запроса.

Ответ 1

ОБНОВЛЕНИЕ: (подробнее см. ниже)

Я бы пошел на что-то вроде этого:

POST /users/:user_id/reset_password

У вас есть коллекция пользователей, где один пользователь указан {user_name}. Затем вы указываете действие для работы, которое в этом случае равно reset_password. Это как сказать "Создать (POST) новое действие reset_password для {user_name}".


Предыдущий ответ:

Я бы пошел на что-то вроде этого:

PUT /users/:user_id/attributes/password
    -- The "current password" and the "new password" passed through the body

У вас будет две коллекции, коллекция пользователей и коллекция атрибутов для каждого пользователя. Пользователь указан :user_id, а атрибут указан password. Операция PUT обновляет адресный элемент коллекции.

Ответ 2

Неаутентифицированные пользователи

Мы делаем запрос PUT на конечную точку api/v1/account/password и запрашиваем параметр с соответствующим адресом электронной почты, чтобы определить учетную запись, для которой пользователь хочет сбросить (обновить) пароль:

PUT : /api/v1/account/password?email={[email protected]}

Примечание. Как отметил @DougDomeny в своем комментарии, передача сообщения электронной почты в виде строки запроса в URL-адресе является угрозой безопасности. Параметры GET не отображаются при использовании https (и вы всегда должны использовать правильное соединение https для таких запросов), но существуют и другие риски безопасности. Вы можете прочитать больше на эту тему в этом блоге здесь.

Передача сообщения электронной почты в теле запроса будет более безопасной альтернативой передаче его в качестве параметра GET:

PUT : /api/v1/account/password

Тело запроса:

{
    "email": "[email protected]"
}

Ответ имеет 202 принятых значения, означающих:

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

Пользователь получит электронное письмо на [email protected] и обработка запроса на обновление зависит от действий, предпринятых по ссылке из электронного письма.

https://example.com/password-reset?token=1234567890

Открытие ссылки из этого электронного письма приведет к появлению формы пароля для сброса в приложении внешнего интерфейса, которое использует маркер пароля для сброса из ссылки в качестве входных данных для скрытого поля ввода (токен является частью ссылки в виде строки запроса). Другое поле ввода позволяет пользователю установить новый пароль. Второй вход для подтверждения нового пароля будет использоваться для проверки на внешнем интерфейсе (для предотвращения опечаток).

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

Когда форма отправляется с новым паролем и токеном в качестве входных данных, происходит процесс сброса пароля. Данные формы будут снова отправлены с запросом PUT но на этот раз с токеном, и мы заменим пароль ресурса новым значением:

PUT : /api/v1/account/password

Тело запроса:

{
    "token":"1234567890",
    "new":"password"
}

Ответ будет 204 без ответа

Сервер выполнил запрос, но ему не нужно возвращать тело объекта, и он может захотеть вернуть обновленную метаинформацию. Ответ МОЖЕТ включать новую или обновленную метаинформацию в форме заголовков объекта, которые, если они присутствуют, ДОЛЖНЫ быть связаны с запрошенным вариантом.

Аутентифицированные пользователи

Для аутентифицированных пользователей, которые хотят изменить свой пароль, запрос PUT может быть выполнен немедленно без электронной почты (учетная запись, для которой мы обновляем пароль, известна серверу). В таком случае в форму будут отправлены два поля:

PUT : /api/v1/account/password

Тело запроса:

{
    "old":"password",
    "new":"password"
}

Ответ 3

Позвольте получить uber-RESTful на секунду. Почему бы не использовать действие DELETE для пароля для запуска reset? Имеет смысл, не так ли? В конце концов, вы фактически отбрасываете существующий пароль в пользу другого.

Это означает, что вы сделали бы:

DELETE /users/{user_name}/password

Теперь два больших оговорки:

  • HTTP DELETE должен быть идемпотентом (причудливое слово для слова "неважно, если вы делаете это несколько раз" ). Если вы делаете стандартные вещи, такие как отправка "Пароль Reset", вы столкнетесь с проблемами. Вы можете обойти эту пометку пользователя/пароль с помощью логического значка "Is Reset". При каждом удалении вы проверяете этот флаг; если он не установлен, вы можете reset ввести пароль и отправить свое письмо. (Обратите внимание, что наличие этого флага может иметь и другие виды использования.)

  • Вы не можете использовать HTTP DELETE через форму, поэтому вам придется сделать вызов AJAX и/или туннелировать DELETE через POST,

Ответ 4

Часто вы не хотите удалять или уничтожать существующий пароль пользователя при первоначальном запросе, поскольку это может быть вызвано (непреднамеренно или намеренно) пользователем, у которого нет доступа к электронной почте. Вместо этого обновите токен reset в записи пользователя и отправьте его по ссылке, включенной в электронное письмо. Нажав на ссылку, вы подтвердите, что пользователь получил токен и пожелал обновить свой пароль. В идеале это также будет чувствительным к времени.

Действие RESTful в этом случае будет POST: запуск действия create на контроллере PasswordResets. Само действие обновит токен и отправит электронное письмо.

Ответ 5

Я действительно ищу ответ, а не значение, чтобы предоставить один, но "reset_password" звучит неправильно для меня в контексте REST, потому что это глагол, а не существительное. Даже если вы говорите, что вы используете существительное "reset action", используя это оправдание, все глаголы являются существительными.

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

Ответ 6

Думаю, лучшая идея:

DELETE /api/v1/account/password    - To reset the current password (in case user forget the password)
POST   /api/v1/account/password    - To create new password (if user has reset the password)
PUT    /api/v1/account/{userId}/password    - To update the password (if user knows is old password and new password)

Что касается подачи данных:

  • reset текущий пароль

    • email следует указывать в теле.
  • Чтобы создать новый пароль (после reset)

    • новый пароль, код активации и адрес электронной почты должны быть указаны в теле.
  • Чтобы обновить пароль (для пользователя loggedIn)

    • старый пароль, новый пароль должен быть указан в теле.
    • UserId в Params.
    • Auth Token в заголовках.

Ответ 7

Есть несколько соображений:

Сброс пароля не идемпотентен

Изменение пароля влияет на данные, используемые в качестве учетных данных для его выполнения, что в результате может сделать недействительными будущие попытки, если запрос будет просто дословно повторен, в то время как сохраненные учетные данные изменились. Например, если токен временного сброса используется для разрешения изменения, как это обычно бывает в ситуации с забытым паролем, этот токен должен истечь при успешном изменении пароля, что снова сводит на нет дальнейшие попытки репликации запроса. Таким образом, подход RESTful к смене пароля, кажется, лучше подходит для POST чем для PUT.

URL с идентификаторами-заполнителями не являются RESTful

Ресурс, который указан как /password-reset/{user_id} подразумевает, что фактический URL-адрес, указывающий на ресурс, должен быть создан с внеполосной информацией (то есть мы должны иметь предварительные знания user_id), а не получен через открытие. Кроме того, предполагается, что мы будем иметь доступ к этой информации во время запроса, что во многих ситуациях не будет иметь место.

Идентификатор или электронная почта в загрузке данных, вероятно, избыточны

Хотя это не относится к REST и может иметь какое-то специальное назначение, часто нет необходимости указывать идентификатор или адрес электронной почты для сброса пароля. Подумайте об этом, зачем вы указали адрес электронной почты как часть данных для запроса, который должен пройти проверку подлинности, так или иначе? Если пользователь просто меняет свой пароль, ему необходимо пройти аутентификацию (через имя пользователя: пароль, адрес электронной почты: пароль или токен доступа, предоставленный через заголовки). Следовательно, у нас есть доступ к их учетной записи с этого шага. Если бы они забыли свой пароль, им был бы предоставлен токен временного сброса (по электронной почте), который они могли бы использовать специально в качестве учетных данных для выполнения изменения. И в этом случае аутентификации с помощью токенов должно быть достаточно для идентификации их учетной записи.

Принимая во внимание все вышесказанное, я считаю, что это правильная схема смены пароля RESTful:

Пользователь знает свой пароль:

Method: POST
url: /v1/account/password
Auth (via headers): [email protected]:my 0ld pa55wOrd
data load: {"password": "This 1s My very New Passw0rd"}

Пользователь не знает свой пароль (пароль сбрасывается по электронной почте):

Method: POST
url: /v1/account/password
Access Token (via headers): pwd_rst_token_b3xSw4hR8nKWE1d4iE2s7JawT8bCMsT1EvUQ94aI
data load: {"password": "This 1s My very New Passw0rd"}

Ответ 8

У меня не было бы того, что изменяет пароль и отправляет им новый, если вы решите использовать метод /users/ {id}/password и придерживайтесь своей идеи, что запрос является собственным ресурсом. т.е./user-password-request/является ресурсом и используется PUT, информация пользователя должна находиться в теле. Я бы не изменил пароль, хотя, Id отправил электронное письмо пользователю, которое содержит ссылку на страницу, содержащую request_guid, которая может быть передана вместе с запросом POST/user/{id}/password/? Request_guid = ххххх

Это изменит пароль, и он не позволит кому-то направить пользователя, запросив смену пароля.

Плюс исходный PUT может завершиться с ошибкой, если есть выдающийся запрос.

Ответ 9

Обновляем зарегистрированный пароль пользователя PUT/v1/users/password - идентифицируем идентификатор пользователя с помощью AccessToken.

Обмен идентификатора пользователя небезопасен. API Restful должен идентифицировать пользователя, используя AccessToken, полученный в заголовке HTTP.

Пример в Spring-boot

@putMapping(value="/v1/users/password")
public ResponseEntity<String> updatePassword(@RequestHeader(value="Authorization") String token){
/* find User Using token */
/* Update Password*?
/* Return 200 */
}