パスワードをリセットするためのRESTfulリソースを構成する適切な方法は何ですか?
このリソースは、パスワードを紛失または忘れたユーザーのためのパスワード再設定ツールです。古いパスワードを無効にし、パスワードを電子メールで送信します。
私が持っている2つのオプションは次のとおりです。
POST /reset_password/{user_name}
または...
POST /reset_password
-Username passed through request body
リクエストはPOSTであるべきだと確信しています。適切な名前を選択したかどうかはあまりわかりません。そして、user_nameがURLを介して渡されるのか、リクエスト本文を介して渡されるのかがわかりません。
PDATE:(さらにコメントする)
私はこのようなものに行きます:
POST /users/:user_id/reset_password
ユーザーのコレクションがあり、単一のユーザーが{user_name}
で指定されています。次に、操作するアクションを指定します。この場合はreset_password
です。 「reset_password
の新しい{user_name}
アクションを作成(POST
)」と言っているようなものです。
前の答え:
私はこのようなものに行きます:
PUT /users/:user_id/attributes/password
-- The "current password" and the "new password" passed through the body
2つのコレクション、ユーザーコレクション、および各ユーザーの属性コレクションがあります。ユーザーは:user_id
で指定され、属性はpassword
で指定されます。 PUT
操作は、コレクションのアドレス指定されたメンバーを更新します。
api/v1/account/password
エンドポイントでPUT
リクエストを行い、ユーザーがパスワードをリセット(更新)したいアカウントを識別するために、対応するアカウントの電子メールにパラメーターが必要です。
PUT : /api/v1/account/password?email={[email protected]}
注:As@ DougDomeny URL内のクエリ文字列として電子メールを渡す彼のコメントはセキュリティリスクです。 https
を使用する場合、GETパラメーターは公開されません(そのような要求には常に適切なhttps
接続を使用する必要があります)が、他のセキュリティリスクが伴います。このトピックの詳細については、 このブログ投稿 。をご覧ください。
要求本文で電子メールを渡すことは、GETパラメーターとして渡すよりも安全な代替手段です。
PUT : /api/v1/account/password
リクエスト本文:
{
"email": "[email protected]"
}
応答には、202
受け入れ応答の意味があります。
要求は処理のために受け入れられましたが、処理は完了していません。要求は、実際に処理が行われるときに許可されない可能性があるため、最終的に実行される場合と実行されない場合があります。このような非同期操作からステータスコードを再送信する機能はありません。
ユーザーは[email protected]
で電子メールを受信し、更新リクエストの処理は、電子メールからのリンクで実行されたアクションに依存します。
https://example.com/password-reset?token=1234567890
このメールからリンクを開くと、非表示の入力フィールドへの入力としてリンクからのリセットパスワードトークンを使用する、フロントエンドアプリケーションのリセットパスワードフォームが表示されます(トークンはクエリ文字列としてリンクの一部です)。別の入力フィールドでは、ユーザーが新しいパスワードを設定できます。新しいパスワードを確認するための2番目の入力は、フロントエンドでの検証に使用されます(入力ミスを防ぐため)。
注:メールでは、ユーザーがパスワードのリセットを初期化していない場合は、電子メールを無視し、現在のパスワードでアプリケーションを通常どおり使用し続けます
新しいパスワードとトークンを入力としてフォームが送信されると、パスワードのリセット処理が行われます。フォームデータはPUT
リクエストで再度送信されますが、今回はトークンを含め、リソースパスワードを新しい値に置き換えます。
PUT : /api/v1/account/password
リクエスト本文:
{
"token":"1234567890",
"new":"password"
}
応答は204
no content応答になります
サーバーは要求を実行しましたが、エンティティ本体を返す必要はなく、更新されたメタ情報を返したい場合があります。応答には、エンティティヘッダーの形式で新しいメタデータまたは更新されたメタ情報が含まれている場合があります。
パスワードを変更したい認証ユーザーの場合、PUT
リクエストはメールなしですぐに実行できます(パスワードを更新するアカウントはサーバーに知られています)。そのような場合、フォームは2つのフィールドを送信します。
PUT : /api/v1/account/password
リクエスト本文:
{
"old":"password",
"new":"password"
}
ちょっと待ってみましょう。パスワードにDELETEアクションを使用してリセットをトリガーしないのはなぜですか?理にかなっていますよね?結局のところ、既存のパスワードを効果的に破棄して、別のパスワードを優先させることになります。
それはあなたがすることを意味します:
DELETE /users/{user_name}/password
次に、2つの大きな注意事項を示します。
HTTP DELETEはべき等であることになっています (「何度もやっても大したことはない」と言うのは派手な言葉です)。 「パスワードリセット」メールを送信するなどの標準的な作業を行っている場合は、問題が発生します。ブール値の「Is Reset」フラグでユーザー/パスワードをタグ付けするこの問題を回避できます。削除するたびに、このフラグをチェックします。設定されていない場合、その後パスワードをリセットしてメールを送信できます。 (このフラグを使用すると、他の用途もあることに注意してください。)
フォームでHTTP DELETEを使用することはできません ですので、AJAXを呼び出すか、POSTでDELETEをトンネルする必要があります。
多くの場合、最初の要求でユーザーの既存のパスワードを削除または破棄したくないのは、これが電子メールにアクセスできないユーザーによって(意図的または意図的に)トリガーされた可能性があるためです。代わりに、ユーザーレコードのリセットパスワードトークンを更新し、メールに含まれるリンクで送信します。リンクをクリックすると、ユーザーがトークンを受信し、パスワードを更新することを確認します。理想的には、これも時間に敏感です。
この場合のRESTfulアクションはPOSTです。PasswordResetsコントローラーでcreateアクションをトリガーします。アクション自体がトークンを更新し、電子メールを送信します。
私は実際に答えを探していますが、答えを提供する意味ではありません-しかし、RESTコンテキストでは、それは名詞ではなく動詞であるため、「reset_password」は間違っているように聞こえます。 「リセットアクション」名詞を実行しています-この正当化を使用して、すべての動詞は名詞です。
また、セキュリティコンテキストを介してユーザー名を取得でき、URLや本文を介してユーザー名を送信する必要がないのと同じ回答を検索しているユーザーには発生しなかった可能性があります。
私はより良いアイデアがあると思う:
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)
データの提供について:
現在のパスワードをリセットするには
リセット後に新しいパスワードを作成するには
loggedInユーザーのパスワードを更新するには
考慮すべきいくつかの考慮事項があります。
パスワードの変更は、それを実行するための資格情報として使用されるデータに影響を与えます。その結果、保存された資格情報が変更されている間にリクエストが単純に繰り返されると、将来の試行が無効になる可能性があります。たとえば、一時的なリセットトークンを使用して変更を許可する場合、パスワードを忘れた場合の慣例であるため、パスワードの変更が成功するとそのトークンは期限切れになり、リクエストの複製の試行がさらに無効になります。したがって、パスワードの変更に対するRESTfulなアプローチは、POST
よりもPUT
に適した仕事のようです。
これはRESTに反するものではなく、特別な目的がある可能性がありますが、パスワードリセットのためにIDまたはメールアドレスを指定する必要はないことがよくあります。何らかの方法で認証を受けることになっているリクエストへのデータの提供?ユーザーが単にパスワードを変更する場合、そのためには認証が必要です(username:password、email:password、またはヘッダー)。したがって、そのステップからアカウントにアクセスできます。パスワードを忘れた場合は、変更を実行するための資格情報として特に使用できる一時的なリセットトークン(電子メール経由)が提供されます。この場合、トークンを介した認証でアカウントを識別できます。
上記のすべてを考慮に入れると、RESTfulなパスワード変更に対する適切なスキームであると私は信じています:
Method: POST
url: /v1/account/password
Access Token (via headers): pwd_rst_token_b3xSw4hR8nKWE1d4iE2s7JawT8bCMsT1EvUQ94aI
data load: {"password": "This 1s My very New Passw0rd"}
/ users/{id}/passwordメソッドを使用することに決めた場合、パスワードを変更して新しいパスワードを送信し、リクエストはそれ自体のリソースであるという考えに固執するものはありません。つまり、/ user-password-request /はリソースであり、PUTを使用しています。ユーザー情報は本文に含める必要があります。ただし、パスワードは変更しません。Idにrequest_guidを含むページへのリンクを含む電子メールをユーザーに送信します。このリンクは、POST/user/{id}/password /?request_guid = xxxxx
それはパスワードを変更し、パスワードの変更を要求することで誰かがユーザーにホースをかけることを許可しません。
さらに、未処理の要求がある場合、最初のPUTが失敗する可能性があります。
ログに記録されたユーザーパスワードPUT/v1/users/passwordを更新します-AccessTokenを使用してユーザーIDを識別します。
ユーザーIDを交換することは安全ではありません。 Restful APIは、HTTPヘッダーで受信したAccessTokenを使用してユーザーを識別する必要があります。
Spring-bootの例
@putMapping(value="/v1/users/password")
public ResponseEntity<String> updatePassword(@RequestHeader(value="Authorization") String token){
/* find User Using token */
/* Update Password*?
/* Return 200 */
}