Как правильно структурировать ресурс RESTful для сброса пароля?
Этот ресурс предназначен для сброса пароля для тех, кто потерял или забыл свой пароль. Он аннулирует их старый пароль и отправляет им пароль по электронной почте.
У меня есть два варианта:
POST /reset_password/{user_name}
или...
POST /reset_password
-Username passed through request body
Я уверен, что запрос должен быть POST. Я менее уверен, что выбрал подходящее имя. И я не уверен, следует ли передавать user_name через URL-адрес или тело запроса.
источник
Неаутентифицированные пользователи
Мы делаем
PUT
запрос наapi/v1/account/password
конечной точке и требуем параметр с соответствующим адресом электронной почты учетной записи, чтобы идентифицировать учетную запись, для которой пользователь хочет сбросить (обновить) пароль:Примечание. Как сказал @DougDomeny в своем комментарии, передача электронного письма в виде строки запроса в URL-адресе представляет собой угрозу безопасности. Параметры GET не отображаются при использовании
https
(и вы всегда должны использовать правильноеhttps
соединение для таких запросов), но есть и другие риски безопасности. Вы можете прочитать больше по этой теме в этом блоге здесь .Передача электронного письма в теле запроса будет более безопасной альтернативой его передаче в качестве параметра GET:
Тело запроса:
Ответ имеет
202
принятый ответ, означающий:Пользователь получит электронное письмо по адресу,
email@example.com
и обработка запроса на обновление зависит от действий, предпринятых со ссылкой из электронного письма.Открытие ссылки из этого электронного письма приведет к переходу к форме сброса пароля во внешнем приложении, которое использует токен сброса пароля из ссылки в качестве входных данных для скрытого поля ввода (токен является частью ссылки в виде строки запроса). Другое поле ввода позволяет пользователю установить новый пароль. Второй ввод для подтверждения нового пароля будет использоваться для проверки на интерфейсе (для предотвращения опечаток).
Примечание: в электронном письме мы также можем упомянуть, что в случае, если пользователь не инициализировал сброс пароля, он / она может игнорировать электронное письмо и продолжать использовать приложение в обычном режиме со своим текущим паролем.
Когда форма будет отправлена с новым паролем и токеном в качестве входных данных, произойдет процесс сброса пароля. Данные формы будут отправлены с
PUT
запросом снова, но на этот раз с токеном, и мы заменим пароль ресурса новым значением:Тело запроса:
Ответ будет
204
не содержание ответаПрошедшие проверку пользователи
Для прошедших проверку подлинности пользователей, которые хотят изменить свой пароль,
PUT
запрос может быть выполнен немедленно, без адреса электронной почты (учетная запись, для которой мы обновляем пароль, известна серверу). В таком случае форма будет содержать два поля:Тело запроса:
источник
Давайте на секунду перейдем к Uber-RESTful. Почему бы не использовать действие DELETE для пароля, чтобы вызвать сброс? Имеет смысл, не так ли? В конце концов, вы фактически отказываетесь от существующего пароля в пользу другого.
Это означает, что вы бы сделали:
Теперь два больших предостережения:
HTTP DELETE должен быть идемпотентным (модное слово для выражения «ничего страшного, если вы сделаете это несколько раз»). Если вы делаете стандартные вещи, например, отправляете электронное письмо «Сброс пароля», то у вас могут возникнуть проблемы. Вы можете обойти это, пометив пользователя / пароль логическим флагом «Сброс». При каждом удалении вы проверяете этот флаг; если он не установлен , то вы можете сбросить пароль и отправить по электронной почте. (Обратите внимание, что наличие этого флага может иметь и другое применение.)
Вы не можете использовать HTTP DELETE через форму , поэтому вам придется сделать вызов AJAX и / или туннелировать DELETE через POST.
источник
DELETE
что здесь хорошо. Полагаю, вы заменили бы пароль случайно сгенерированным, так что этоDELETE
может ввести вас в заблуждение. Я предпочитаюCreate (POST) new reset_password action
, где существительное (ресурс), над которым вы будете действовать, - это "действие reset_password". Это также хорошо подходит для отправки электронных писем, поскольку действие инкапсулирует все эти детали более низкого уровня.POST
не идемпотентный.Часто вы не хотите удалять или уничтожать существующий пароль пользователя при первоначальном запросе, поскольку это могло быть инициировано (непреднамеренно или намеренно) пользователем, не имеющим доступа к электронной почте. Вместо этого обновите токен сброса пароля в записи пользователя и отправьте его по ссылке, содержащейся в электронном письме. Щелчок по ссылке подтвердит, что пользователь получил токен и хочет обновить свой пароль. В идеале это также должно быть связано со временем.
Действие RESTful в этом случае будет POST: запуск действия create на контроллере PasswordResets. Само действие обновит токен и отправит электронное письмо.
источник
На самом деле я ищу ответ, не собираясь его давать, но "reset_password" звучит для меня неправильно в контексте REST, потому что это глагол, а не существительное. Даже если вы говорите, что выполняете существительное «сбросить действие» - используя это обоснование, все глаголы являются существительными.
Кроме того, кому-то, ищущему тот же ответ, могло и не приходить в голову, что вы можете получить имя пользователя через контекст безопасности и не должны вообще отправлять его через URL-адрес или тело, что заставляет меня нервничать.
источник
reset-password
звучит как глагол, но вы можете легко перевернуть его (password-reset
), чтобы превратить его в существительное. И если вы смоделировали свое приложение с помощью Event Sourcing или даже если у вас просто есть какой-либо вид аудита, имеет смысл, что у вас действительно будет реальный объект с этим именем и может даже разрешить GET для пользователей или администраторов. история (очевидно, маскируя текст пароля). Совершенно не заставляет меня нервничать. А что касается автоматического выбора имени пользователя на стороне сервера - вы можете, но как тогда справляться с такими вещами, как администрирование / олицетворение?reset-password
удалось хорошо описать его эффекты.Я думаю, что лучше было бы:
Относительно предоставления данных:
Чтобы сбросить текущий пароль
Создать новый пароль (после сброса)
Чтобы обновить пароль (для вошедшего в систему пользователя)
источник
Следует принять во внимание несколько соображений:
Сброс пароля не идемпотентен
Изменение пароля влияет на данные, используемые в качестве учетных данных для его выполнения, что в результате может сделать недействительными будущие попытки, если запрос будет просто повторяться дословно, в то время как сохраненные учетные данные изменились. Например, если для разрешения изменения используется временный токен сброса, как это обычно бывает в ситуации с забытым паролем, срок действия этого токена должен истечь после успешной смены пароля, что снова аннулирует дальнейшие попытки репликации запроса. Таким образом, RESTful-подход к смене пароля кажется более подходящей задачей,
POST
чемPUT
.Идентификатор или адрес электронной почты в загрузке данных, вероятно, избыточны
Хотя это не противоречит REST и может иметь какое-то специальное назначение, часто нет необходимости указывать идентификатор или адрес электронной почты для сброса пароля. Подумайте, зачем вам указывать адрес электронной почты как часть данных для запроса, который должен так или иначе проходить аутентификацию? Если пользователь просто меняет свой пароль, для этого ему необходимо пройти аутентификацию (с помощью имени пользователя: пароля, электронной почты: пароля или токена доступа, предоставленного через заголовки). Следовательно, с этого шага у нас есть доступ к их учетной записи. Если бы они забыли свой пароль, им был бы предоставлен временный токен сброса (по электронной почте), который они могут использовать специально в качестве учетных данных для выполнения изменения. И в этом случае аутентификации с помощью токена должно быть достаточно для идентификации их учетной записи.
Принимая во внимание все вышеперечисленное, вот что я считаю правильной схемой для смены пароля RESTful:
источник
POST
сравненияPUT
RFC 7231, указывается, что частичное обновление может быть достигнуто за счет перекрытия данных двух ресурсов, но сомнительно/v1/account/password
, действительно ли что-то подобное действительно компенсирует хороший ресурс. КакPOST
и швейцарский армейский нож в Интернете, который можно использовать, если ни один из других методов невозможен, рассмотрениеPATCH
также может быть выбором для установки нового пароля.У меня не было бы чего-то, что меняет пароль и отправляет им новый, если вы решите использовать метод / users / {id} / password и будете придерживаться вашей идеи, что запрос является собственным ресурсом. т.е. / user-password-request / - это ресурс и используется PUT, информация о пользователе должна быть в теле. Я бы не стал менять пароль, я бы отправил пользователю электронное письмо, которое содержит ссылку на страницу, содержащую request_guid, которую можно передать вместе с запросом на POST / user / {id} / password /? Request_guid = ххххх
Это изменит пароль, и это не позволит кому-либо атаковать пользователя, запрашивая смену пароля.
Кроме того, первоначальный запрос PUT может завершиться ошибкой, если есть невыполненный запрос.
источник
Мы обновляем пароль зарегистрированного пользователя PUT / v1 / users / password - идентифицируем идентификатор пользователя с помощью AccessToken.
Обмен идентификатора пользователя небезопасен. Restful API должен идентифицировать пользователя с помощью AccessToken, полученного в HTTP-заголовке.
Пример в Spring-boot
источник