122

パスワードをリセットするためのRESTfulリソースを構築する適切な方法は何ですか?

このリソースは、パスワードを紛失または忘れた人のためのパスワードリセッタとして使用することを目的としています。古いパスワードを無効にし、パスワードを電子メールで送信します。

私が持っている2つのオプションは次のとおりです。

POST /reset_password/{user_name}

また...

POST /reset_password
   -Username passed through request body

リクエストはPOSTである必要があります。適切な名前を選択したことに自信がありません。また、user_nameをURLまたはリクエスト本文のどちらで渡す必要があるのか​​わかりません。

4

9 に答える 9

118

認証されていないユーザー

PUTエンドポイントでリクエストを実行しapi/v1/account/password、ユーザーがパスワードをリセット(更新)するアカウントを識別するために、対応するアカウントの電子メールを含むパラメーターが必要です。

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

注: @DougDomenyがコメントで述べたように、URLでクエリ文字列としてメールを渡すことはセキュリティ上のリスクです。GETパラメータは、使用時に公開されません(このような要求には常に適切な接続を使用する必要があります)が、他にもセキュリティ上のリスクがあります。このトピックの詳細については、こちらのブログ投稿をご覧くださいhttpshttps

リクエスト本文でメールを渡すことは、GETパラメータとして渡すよりも安全な方法です。

PUT : /api/v1/account/password

リクエスト本文:

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

応答には、次の意味の202受け入れられた応答があります。

リクエストは処理のために受け入れられましたが、処理は完了していません。リクエストは、実際に処理が行われるときに許可されない可能性があるため、最終的に処理される場合とされない場合があります。このような非同期操作からステータスコードを再送信する機能はありません。

ユーザーはで電子メールを受信しemail@example.com、更新要求の処理は、電子メールからのリンクで実行されたアクションによって異なります。

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

この電子メールからリンクを開くと、フロントエンドアプリケーションのパスワードリセットフォームに移動します。このフォームは、リンクからのパスワードリセットトークンを非表示の入力フィールドの入力として使用します(トークンはクエリ文字列としてリンクの一部です)。別の入力フィールドを使用すると、ユーザーは新しいパスワードを設定できます。新しいパスワードを確認するための2番目の入力は、フロントエンドでの検証に使用されます(タイプミスを防ぐため)。

注: メールでは、ユーザーがパスワードのリセットを初期化しなかった場合、メールを無視して、現在のパスワードで通常どおりアプリケーションを使用し続けることができることにも言及できます。

新しいパスワードと入力としてのトークンを使用してフォームが送信されると、パスワードのリセットプロセスが実行されます。フォームデータはPUTリクエストとともに再度送信されますが、今回はトークンを含み、リソースパスワードを新しい値に置き換えます。

PUT : /api/v1/account/password

リクエスト本文:

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

応答は204コンテンツなしの応答になります

サーバーは要求を実行しましたが、エンティティ本体を返す必要はなく、更新されたメタ情報を返したい場合があります。応答には、エンティティヘッダーの形式で新しいまたは更新されたメタ情報が含まれる場合があります。これらのメタ情報が存在する場合は、要求されたバリアントに関連付ける必要があります。

認証されたユーザー

パスワードを変更したい認証済みユーザーの場合、PUT要求は電子メールなしですぐに実行できます(パスワードを更新しているアカウントはサーバーに認識されています)。このような場合、フォームは2つのフィールドを送信します。

PUT : /api/v1/account/password

リクエスト本文:

{
    "old":"password",
    "new":"password"
}
于 2015-10-28T11:13:17.670 に答える
63

更新:(以下にさらにコメントする)

私はこのようなものに行きます:

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

ユーザーコレクションと、ユーザーごとの属性コレクションの2つのコレクションがあります。ユーザーはで指定され:user_id、属性はで指定されpasswordます。このPUT操作により、コレクションのアドレス指定されたメンバーが更新されます。

于 2010-06-19T21:11:31.150 に答える
21

ちょっと超RESTfulにしましょう。パスワードにDELETEアクションを使用して、リセットをトリガーしてみませんか?理にかなっていますね。結局のところ、既存のパスワードを事実上破棄して、別のパスワードを優先することになります。

それはあなたがすることを意味します:

DELETE /users/{user_name}/password

ここで、2つの大きな注意事項があります。

  1. HTTP DELETEはべき等であると想定されています(「複数回実行しても大したことはない」という意味の派手な言葉)。「パスワードリセット」メールを送信するなどの標準的な作業を行っている場合は、問題が発生します。ブール値の「IsReset」フラグを使用してユーザー/パスワードにタグを付けることで回避できます。削除するたびに、このフラグをチェックします。設定されていない場合、パスワードをリセットしてメールを送信できます。(このフラグを持つことは他の用途もあるかもしれないことに注意してください。)

  2. フォームを介してHTTPDELETEを使用することはできないため、AJAX呼び出しを行うか、POSTを介してDELETEをトンネリングする必要があります。

于 2010-06-19T21:34:39.063 に答える
12

多くの場合、最初のリクエストでユーザーの既存のパスワードを削除または破棄したくない場合があります。これは、電子メールにアクセスできないユーザーによって(意図的または意図的に)トリガーされた可能性があるためです。代わりに、ユーザーレコードのリセットパスワードトークンを更新し、電子メールに含まれているリンクで送信します。リンクをクリックすると、ユーザーがトークンを受け取り、パスワードを更新したいことを確認できます。理想的には、これも時間に敏感です。

この場合のRESTfulアクションはPOSTになります。つまり、PasswordResetsコントローラーで作成アクションをトリガーします。アクション自体がトークンを更新し、電子メールを送信します。

于 2013-01-28T20:59:18.797 に答える
12

私は実際に答えを探していますが、答えを提供するつもりはありませんが、「reset_password」は名詞ではなく動詞であるため、RESTコンテキストでは間違っているように聞こえます。「リセットアクション」名詞を実行していると言っても、この正当化を使用すると、すべての動詞は名詞になります。

また、セキュリティコンテキストを介してユーザー名を取得でき、URLや本文を介してユーザー名を送信する必要がないため、同じ回答を検索している人には発生しなかった可能性があり、緊張します。

于 2014-01-06T20:24:10.227 に答える
8

私はより良いアイデアは次のようになると思います:

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を本文に入力する必要があります。
  • パスワードを更新するには(ログインユーザーの場合)

    • 古いパスワード、新しいパスワードは本文に記載する必要があります。
    • ParamsのUserId。
    • ヘッダーの認証トークン。
于 2017-11-24T14:25:58.123 に答える
5

考慮すべき点がいくつかあります。

パスワードのリセットはべき等ではありません

パスワードの変更は、それを実行するためのクレデンシャルとして使用されるデータに影響を与えます。その結果、保存されているクレデンシャルが変更されている間に要求が逐語的に繰り返されると、将来の試行が無効になる可能性があります。たとえば、パスワードを忘れた場合の通常のように、一時的なリセットトークンを使用して変更を許可する場合、パスワードの変更が成功するとそのトークンの有効期限が切れます。これにより、リクエストの複製の試行が無効になります。POSTしたがって、パスワード変更へのRESTfulなアプローチは、よりも適した仕事のようですPUT

データロードのIDまたは電子メールはおそらく冗長です

これは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"}
于 2018-06-23T13:11:40.890 に答える
2

/ users / {id} / passwordメソッドを使用することにした場合、パスワードを変更して新しいパスワードを送信するものはなく、リクエストは独自のリソースであるという考えに固執します。つまり、/ user-password-request /はリソースであり、PUTを使用しているため、ユーザー情報は本文に含める必要があります。パスワードは変更しませんが、リクエストと一緒にPOST / user / {id} / password /?request_guid=に渡すことができるrequest_guidを含むページへのリンクを含むメールをユーザーに送信します。 xxxxx

それはパスワードを変更するでしょう、そしてそれは誰かがパスワードの変更を要求することによってユーザーをホースでつなぐことを許しません。

さらに、未処理の要求がある場合、最初のPUTが失敗する可能性があります。

于 2014-09-03T02:51:50.203 に答える
0

ログに記録されたユーザーのパスワードPUT/v1 / users/passwordを更新します-AccessTokenを使用してユーザーIDを識別します。

ユーザーIDの交換は安全ではありません。Restful APIは、HTTPヘッダーで受信したAccessTokenを使用してユーザーを識別する必要があります。

スプリングブートの例

@putMapping(value="/v1/users/password")
public ResponseEntity<String> updatePassword(@RequestHeader(value="Authorization") String token){
/* find User Using token */
/* Update Password*?
/* Return 200 */
}
于 2018-02-28T15:38:33.157 に答える