79

パスワード/ログアウトの変更中にdbにアクセスせずにJWTを無効にするベストプラクティスを知りたいです。

ユーザーデータベースにアクセスして上記の2つのケースを処理するために、以下のアイデアがあります。

1.パスワードが変更された場合、ユーザーデータベースに保存されているパスワード(ハッシュ)を確認します。

2.ログアウトの場合、最終ログアウト時間をユーザーデータベースに保存するため、トークンの作成時間とログアウト時間を比較することで、このケースを無効にすることができます。

しかし、これら 2 つのケースでは、ユーザーが API にアクセスするたびにユーザー db にアクセスするという犠牲が伴います。ベスト プラクティスを歓迎します。

更新: db にアクセスせずに JWT を無効にできるとは思えません。だから私は解決策を思いつきました。回答を投稿しました。ご不明な点がございましたら、お気軽にお問い合わせください。

4

5 に答える 5

17

なんらかの方法でデータベースを使用せずに、トークンを任意に無効にする方法を私は知りません。

複数のデバイスでサービスにアクセスできる場合は、アプローチ 2 に注意してください。次のシナリオを検討してください...

  • ユーザーは iPad でサインインし、トークン 1 が発行されて保存されます。
  • ユーザーが Web サイトにサインインします。トークン 2 が発行されました。ユーザーがログアウトします。
  • ユーザーが iPad を使用しようとしました。ユーザーが Web サイトからログアウトする前にトークン 1 が発行されました。トークン 1 は現在無効と見なされています。

データベース ストレージも必要ですが、リフレッシュ トークンのアイデアを検討することをお勧めします。

同様の問題に関する適切な SO ディスカッションについては、こちらも参照してください。特定の IanB のソリューションは、いくつかの db 呼び出しを節約します。

提案された解決策 個人的には、これは私がそれにアプローチする方法です...ユーザー認証は、有効期限が短い(たとえば15分)アクセストークンと、はるかに長い期間または無期限に有効なリフレッシュトークンで発行されます。この更新トークンのレコードをデータベースに保存します。

ユーザーが「アクティブ」なときはいつでも、毎回新しい認証トークンを発行します (毎回 15 分間有効)。ユーザーが 15 分以上アクティブになっておらず、リクエストを行った場合 (期限切れの jwt を使用した場合) は、更新トークンの有効性を確認してください。有効な場合 (db チェックを含む)、新しい認証トークンを発行します。

ユーザーがデバイスまたは Web サイトを介して「ログアウト」した場合、クライアント側のアクセス リフレッシュ トークンの両方を破棄し、重要なことに、使用されたリフレッシュ トークンの有効性を取り消します。ユーザーがいずれかのデバイスでパスワードを変更した場合、すべての更新トークンを取り消して、アクセス トークンの有効期限が切れるとすぐに再度ログインするよう強制します。これにより「不確実性の窓」が残りますが、毎回データベースにアクセスしないと避けられません。

このアプローチを使用すると、多くの主要な Web アプリで見られるように、必要に応じてユーザーが特定のデバイスへのアクセスを「取り消す」ことができる可能性も開かれます。

于 2015-02-27T08:35:34.487 に答える
9

ここで何かが欠けているかどうかはわかりませんが、受け入れられた答えは必要以上に複雑であることがわかりました。

API リクエストごとにトークンを検証または無効化するには、db をヒットする必要があることがわかりますが、ここにあるように、全体のプロセスはより簡単になる可能性があります。

jwt が作成されるたびに、つまりログイン時またはパスワードの変更/リセット時に、ユーザー ID を持つ jwt をテーブルに挿入し、各 jwt の jti (基本的には uuid 番号) を維持します。同じ jti が jwt ペイロードにも入ります。事実上、jti は jwt を一意に識別します。アカウントが複数のデバイスまたはブラウザーからアクセスされる場合、ユーザーは同時に複数の jwt を持つことができます。この場合、jti はデバイスまたはユーザー エージェントを区別します。

したがって、テーブル スキーマは次のようになります。ユーザーID。(そしてもちろん主キー)

各 API について、jti がテーブルにあるかどうかを確認します。これは、jwt が有効であることを意味します。

ユーザーがパスワードを変更またはリセットすると、そのユーザー ID のすべての jti がデータベースから削除されます。新しい jti を持つ新しい jwt を作成してテーブルに挿入します。これにより、パスワードを変更またはリセットしたものを除く、他のすべてのデバイスおよびブラウザーからのすべてのセッションが無効になります。

ユーザーがログアウトするとき、そのユーザーの特定の jti を削除しますが、すべてではありません。シングル ログインはありますが、シングル ログアウトはありません。そのため、ユーザーがログアウトするときに、すべてのデバイスからログアウトする必要はありません。ただし、すべての jtis を削除すると、すべてのデバイスからもログアウトされます。

したがって、それは 1 つのテーブルであり、日付の比較はありません。また、リフレッシュ トークンを使用する場合も使用しない場合も同様です。

ただし、データベースの干渉と遅延の可能性を最小限に抑えるために、キャッシュの使用は処理時間の面で物事を容易にするのに役立ちます。

注:反対票を投じる場合は、理由を付けてください。

于 2016-12-06T06:34:12.817 に答える
0

ユーザーがパスワードを変更している場合は、そこでデータベースにアクセスします。しかし、承認のためにデータベースにアクセスしたくありませんか?

ユーザーごとの文字列を格納することの利点を発見しました。また、一緒にハッシュされたグローバル共有文字列により、JWT 実装で最も柔軟性が得られます。この特定のケースでは、グローバル文字列で使用するパスワードのハッシュを保存し、それらを一緒にハッシュして JWT シークレットを作成します。

于 2016-08-30T15:04:43.387 に答える
-3

@gopinathの回答にのみ同意します。すべてのトークンの有効期限が切れたときにパスワードの変更時間を削除する必要があることを1つ追加したいだけです。たとえば、通常の変更を保存するだけでなく、すべてのトークンの有効期限が3日間に設定されているとします。データベースのパスワード時間 有効期限を 3 日に設定することもできます。これより前のトークンは明らかに期限切れになるため、すべてのトークンを再度確認して、有効期限がパスワード時間を変更するかどうかを確認する必要はありません。

于 2016-01-11T17:32:55.273 に答える