Проверить / сменить пароль через REST API - PullRequest
4 голосов
/ 22 ноября 2011

Я хочу изменить пароль пользователя через REST API.Это не функция забытого или сброшенного пароля, а зарегистрированный пользователь, желающий изменить свой пароль.

В форме требуется текущий пароль, новый пароль и подтверждение нового пароля.Однако я хочу проверить каждое поле формы, когда пользователь заполняет его.Это тривиально для newPassword и confirmNewPassword (на стороне клиента), но не для currentPassword.В настоящее время выполняется обновление объекта User с помощью PUT /users/:id.Если передан параметр пароля, я проверяю параметр currentPassword и проверяю его правильно перед сохранением.Однако, для проверки, я не уверен в лучшем подходе.

У меня также есть POST /users/validate - не уверен, что это также лучше.Это проверяет объект User как для создания, так и для обновления, но проверяет только те поля, которые принадлежат объекту User (email, username, password).currentPassword не один из них.Хотите знать, как справиться с этим.Некоторые вещи, которые я рассмотрел:

POST /users/check_password, POST /users/validate (добавление проверки для currentPassword, если этот параметр передан, и проверка соответствия currentPassword существующему паролю пользователя) и POST /users/:id/validate (отдельная проверкасуществующий пользователь, требующий currentPassword).

Будем весьма признательны за любые мысли или советы.Мое первое приложение, которое предоставляет функциональность только через REST API.

Ответы [ 5 ]

8 голосов
/ 06 января 2015

Я начну с указания, что аутентификация часто обрабатывается вне модели REST. Когда пользователь предоставляет свои учетные данные, он не предоставляет REpresentation состояния своего аккаунта (REST); и не ответ они получают такое представление. Поскольку состояние ресурса учетной записи пользователя не включает как «текущий», так и «новый» пароли, предоставление как «текущего», так и «нового» пароля в запросе никогда не может действительно соответствовать модели REST, но профессионалы часто описывают «континуум» RESTfulness, причем некоторые API полностью RESTful, а другие находятся между RPC (удаленный вызов процедуры) и REST.

Нередко имеется компонент RESTful API, который обрабатывает обслуживание моделей данных, и компонент RPC API, который обрабатывает учетные записи пользователей. Вы должны выбрать между двумя. Если ваш проект включает в себя суперпользователей, которые управляют несколькими учетными записями пользователей, я бы посоветовал попытаться включить это в API REST. Если каждый пользователь управляет только своей учетной записью, я бы предложил RPC.

Если вы решили использовать REST для управления учетными записями, то вы должны выбрать подходящий метод HTTP (GET, POST, DELETE, HEADERS и т. Д.). Очевидно, вам нужен метод, который будет влиять на изменения на сервере (POST, PUT, DELETE и т. Д.). В отличие от вывода пользователя orbfish, приведенного выше, я хочу сказать, что PUT будет подходящим методом при определенных ограничениях.

From RFC 2616 , который формально определяет наши методы HTTP:

"Методы также могут иметь свойство idempotence в том смысле, что (кроме ошибок, связанных с ошибкой или истечением срока действия) побочные эффекты от N> 0 идентичных запросов такие же, как и для одного запроса. Методы GET, HEAD, PUT и DELETE разделяют это свойство. Кроме того, методы OPTIONS и TRACE НЕ ДОЛЖНЫ иметь побочных эффектов и поэтому являются идемпотентными по своей природе. "

Идемпотентность здесь означает, что если мы сделаем один и тот же запрос n раз подряд, состояние сервера под воздействием n -го запроса будет таким же, как состояние сервера под влиянием первого запроса. Пользователь orbfish правильно отмечает, что если мы сделаем запрос:

PUT /users/:id/account {current-password: 'a', new-password: 'b'}

и повторите это:

PUT /users/:id/account {current-password: 'a', new-password: 'b'}

что наш первый запрос должен получить ответ, указывающий на успех, и наш второй запрос должен получить ответ, указывающий на ошибку. Однако идемпотентность PUT требует только того, чтобы состояние сервера было одинаковым после обоих запросов. И это: после первого запроса пароль пользователя «b», а после второго запроса пароль пользователя «b».

Я упомянул ограничения выше. Возможно, вы захотите заблокировать пользователя после m попыток изменить пароль безуспешно; это обеспечило бы защиту от атак методом перебора паролей. Однако это нарушит идемпотентность запроса: отправьте действительный запрос пароля один раз, и вы измените свой пароль, отправьте его m больше раз, и сервер заблокирует вас.

Указывая метод PUT, вы сообщаете всем клиентам, что отправка запроса безопасна столько раз, сколько необходимо. Если я, как клиент, отправляю запрос PUT, и наше соединение прерывается, так что я не получаю ваш ответ, я знаю, что безопасно повторно отправить мой PUT, потому что он идемпотентен: идемпотентность означает, что если вы получаете оба запроса, то он будет таким же для вашего сервера, как и для получения. Но если вы собираетесь заблокировать меня из-за неудачного запроса, отправлять второй запрос небезопасно, пока я не узнаю, получил ли вы первый.

По этой причине вы можете рассмотреть PATCH или POST. Я бы предложил использовать PATCH. Принимая во внимание, что POST описывается как добавление нового ресурса в список или добавление данных к существующему ресурсу, PATCH описывается как «частичное обновление» ресурса по известному URI. И в отличие от PUT, PATCH не обязательно должен быть идемпотентом.

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

Мне не нравятся / check_password или / validate, потому что они глаголы; Ваш первый «пользователь обновления» лучше ОТДЫХ.

Вы можете добавить currentPassword к своему объекту User в виде непрошеного поля или как часть заголовка Authentication (имя пользователя: пароль).

Я бы определенно изменил это с PUT на POST, потому что один и тот же вызов с тем же паролем currentPassword не может быть выполнен дважды (PUT идемпотентен).

2 голосов
/ 29 марта 2016

Другой вариант - создать суррогатные ресурсы на user.Если вы используете HATEOAS, вы можете перейти по ссылке user/x/pwdchange с ресурса user.И я хочу уточнить, что pwdchange понимается как существительное / ресурс, а не как глагол:

GET /user/jsmith/pwdchange     List of password change requests (history)
POST /user/jsmith/pwdchange    Create password change request, return id=1
GET /user/jsmith/pwdchange/1   Get password change resource, which would
                               include the outcome (success, failure, etc)

Итак, вкратце, я создаю ресурс с именем 'pwdchange', который полностью соответствуетREST-представление проблемного домена.

2 голосов
/ 09 января 2015

Вы изменяете свойство пользовательского ресурса (т.е. пароль). Если вы используете HTTP Basic для своей авторизации, вы уже предоставляете текущий пароль, поэтому нет необходимости повторять его. Я бы просто ПОСТАВИЛ весь пользовательский ресурс с новым паролем. Пример:

PUT /users/fiddlerpianist HTTP/1.1
Content-Type: application/json
Authorization: Basic ZmlkZGxlcnBpYW5pc3Q6bXlub3Rzb2F3ZXNvbWVvbGRwYXNzd29yZA==

{
    "password": "My awesome new password that no one will ever be able to guess!"
}

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

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

ИЗМЕНЕНО ДЛЯ ДОБАВЛЕНИЯ: обратите внимание, что в приложении RESTful отсутствует понятие «вход в систему». Связь между клиентом и сервером полностью без сохранения состояния (это полезная нагрузка и метод, который сообщает о состоянии). Кроме того, в действительности нет необходимости в концепции валидации в том виде, в каком вы ее описываете, поскольку запрос на изменение состояния ресурса может быть удовлетворен с помощью 200 OK (если он действителен) или 400 Bad (если недействителен). ).

1 голос
/ 23 ноября 2011

Вы можете подумать, почему вам нужно подтвердить текущий пароль, как только он введен. Я не видел, чтобы сайт делал это. Во-вторых, совершенно нормально иметь сервис, который просто что-то проверяет. Это называется быть практичным стихом, избивая себя, пытаясь быть ОТЛИЧНЫМ

...