RESTful сброс пароля - PullRequest
       21

RESTful сброс пароля

85 голосов
/ 20 июня 2010

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

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

У меня есть два варианта:

POST /reset_password/{user_name}

или ...

POST /reset_password
   -Username passed through request body

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

Ответы [ 9 ]

56 голосов
/ 28 октября 2015

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

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

PUT : /api/v1/account/password?email={email@example.com}

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

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

PUT : /api/v1/account/password

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

{
    "email": "email@example.com"
}

Ответ имеет 202 принято значение ответа:

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

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

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"
}
48 голосов
/ 20 июня 2010

ОБНОВЛЕНИЕ: (далее к комментарию ниже)

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

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 обновляет адресуемый член коллекции.

17 голосов
/ 20 июня 2010

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

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

DELETE /users/{user_name}/password

Теперь, два больших предостережения:

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

  2. Вы не можете использовать HTTP-УДАЛЕНИЕ через форму , поэтому вам придется сделать вызов AJAX и / или туннелировать УДАЛЕНИЕ через POST.

11 голосов
/ 29 января 2013

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

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

8 голосов
/ 07 января 2014

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

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

5 голосов
/ 24 ноября 2017

Я думаю, что лучшая идея будет:

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)

Относительно предоставления данных:

  • Для сброса текущего пароля

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

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

    • старый пароль, новый пароль должен быть указан в теле.
    • UserId в параметрах.
    • Auth токен в заголовках.
3 голосов
/ 23 июня 2018

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

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

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

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

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

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

Method: POST
url: /v1/account/password
Access Token (via headers): pwd_rst_token_b3xSw4hR8nKWE1d4iE2s7JawT8bCMsT1EvUQ94aI
data load: {"password": "This 1s My very New Passw0rd"}
2 голосов
/ 03 сентября 2014

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

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

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

0 голосов
/ 28 февраля 2018

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

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

Пример в весенней загрузке

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