この記事の内容は SpringBoot に JWT 認証を組み込む方法 (コード付き) です。一定の参考価値があります。必要な友人は参考にしてください。お役に立てば幸いです。 . 役に立ちます。
1. JWT について
1.1 JWT とは
決まり文句の始まり、このようなツールを使用したい場合は、まず次のことを知っておく必要があります。質問。
それでは、JWT とは何ですか?以下は、jwt 公式 Web サイトにある JWT の紹介を私が翻訳したものです。
JSON Web Token (JWT) は、JSON オブジェクトを使用して関係者間で情報を安全に送信するためのコンパクトで独立した方法を定義するオープン スタンダード (RFC 7519) です。
JWT が実際には、複数のポイント間で JSON で表されるデータを安全に送信するためのオープン標準であることがわかりました。送信プロセス中、JWT は文字列の形で私たちの視界に表示されます。この文字列内の情報は、デジタル署名によって検証および信頼できます。 (推奨: Java チュートリアル )
実際の開発における JWT のアプリケーション シナリオは何ですか?
これは、JWT の最も一般的な使用シナリオと考えてください。フロントエンド インターフェイスでは、ユーザーが正常にログインすると、バックエンドから返された JWT が受信されます。後続のリクエストには、バックエンドのルート、サービス、リソースにアクセスするための資格情報としてバックエンドから返された JWT が含まれます。
JWT を使用して複数の当事者間で情報を転送すると、ある程度のセキュリティが確保されます。たとえば、JWT は HMAC、RSA 非対称暗号化アルゴリズム、および ECDSA デジタル署名アルゴリズムを使用して、 JWT の認証. 署名により、メッセージの送信者が実際の送信者であることを確認でき、ヘッダーとペイロードの署名計算を使用して、送信されたメッセージが改ざんされていないかどうかを検証することもできます。
一般に、JWT は header.payload.signature
の 3 つの部分で構成される文字列です。インターネット上には投稿が多すぎます。この部分を紹介するにはここで簡単に説明します。
header
は、使用される署名アルゴリズムとトークンのタイプで構成されます。たとえば、トークンのタイプは JWT などのオープン標準であり、使用される署名 アルゴリズムは HS256
、つまり HmacSHA256
アルゴリズムです。他の暗号化アルゴリズムには、HmacSHA512
、SHA512withECDSA
などがあります。
次に、2 つの属性を含むこの JSON オブジェクトを文字列に変換し、Base64 エンコーディングを使用して最終的に JWT ヘッダーを形成します。
ペイロード
より簡単に言うと、これは requestBody のデータと似ています。タイプは、事前宣言、カスタム、プライベートの 3 つだけです。 iss
送信者と同様、exp
有効期限はすべて事前に登録されたステートメントです。
ペイロード内のデータの事前宣言は必須ではありませんが、公式に推奨されています。次に、requestBody に似たこの JSON 文字列が Base64 エンコードされて、JWT の 2 番目の部分が形成されます。
署名
を生成する場合は、jwt カスタム構成アイテム内のシークレットを使用する必要があります。これは、Hmac アルゴリズム暗号化に必要なキーです。以前に Base64 でエンコードされたヘッダーとペイロードを .
で接続し、カスタム キーを使用してメッセージに署名し、最後に署名を生成します。
生成された署名は、メッセージが送信中に変更されていないことを確認するために使用されます。署名に非対称暗号化アルゴリズムを使用する場合、JWT の送信者がペイロードで宣言された送信者と同一人物であるかどうかを検証するために使用することもできます。
コードは次のとおりです。
public String createJwt(String userId, String projectId) throws IllegalArgumentException, UnsupportedEncodingException { Algorithm al = Algorithm.HMAC256(secret); Instant instant = LocalDateTime.now().plusHours(outHours).atZone(ZoneId.systemDefault()).toInstant(); Date expire = Date.from(instant); String token = JWT.create() .withIssuer(issuer) .withSubject("userInfo") .withClaim("user_id", userId) .withClaim("project_id", projectId) .withExpiresAt(expire) .sign(al); return token; }
渡された 2 つのクレームはプロジェクト内のカスタム ペイロード、al
は選択されたアルゴリズム、secret
は情報に署名するためのキーです。subject
はトークンの件名であり、withExpiresAt
はトークンの有効期限を示します。
ユーザーがシステムに正常にログインすると、トークンが戻りパラメータとして使用され、フロントエンドに返されます。
トークンがフロントエンドに返された後、バックエンドが行う必要があるのは、トークンが正当であるかどうか、およびサーバーのリソースにアクセスできるかどうかを検証することです。 。主に以下の方法で確認できます。
JWTVerifier
を使用してトークンを解析します。これは、トークンが正当かどうかを確認する最初のステップです。たとえば、次から渡されたトークンなどです。フロントエンドが意味のある文字列を持たない文字列である場合、このステップでエラーがスローされる可能性があります。サンプルコードは以下のとおりです。
try { Algorithm algorithm = Algorithm.HMAC256(secret); JWTVerifier verifier = JWT.require(algorithm).build(); DecodedJWT jwt = verifier.verify(token); } catch (JWTVerificationException e) { e.printStackTrace(); }
JWTVerifier は、シークレット署名と指定されたクレームを指定するアルゴリズムを使用して、トークンの正当性を検証できます。
トークンが有効であると判断した後、トークンの正当性を検証します。
try { Algorithm algorithm = Algorithm.HMAC256(secret); JWTVerifier verifier = JWT.require(algorithm).build(); DecodedJWT jwt = verifier.verify(token); if (jwt.getExpiresAt().before(new Date())) { System.out.println("token已过期"); return null; } } catch (JWTVerificationException e) { e.printStackTrace(); return null; }
トークンの有効期限が切れると、サーバー リソースへのアクセスは許可されません。具体的なプロセスは以下の通りです。
上記で作成したトークンの有効期間は、2 時間として構成可能であり、ユーザーがログインして継続的に作業することを前提としています。 1 時間 59 分で、非常に重要な操作を実行するときに [OK] をクリックすると、トークンの有効期限が切れました。プログラムに保護戦略がなければ、ユーザーの 2 時間近くの作業が無駄になってしまいます。
このような問題に遭遇すると、これまでのプロセス設計は必然的に再構築に直面することになります。ユーザーがログインした後、操作ごとにトークンの有効期限を更新する必要があるのではないかという疑問があるかもしれません。
次に質問が来ます。トークンは 3 つのコンテンツ header.payload.signature
で構成されており、有効期限はペイロードに属していることがわかっています。有効期限が変更された場合生成されたペイロードのハッシュは、最後に生成されたものとは異なるはずです。
つまり、これはまったく新しいトークンです。フロントエンドはこの新しいトークンをどのように受け取るのでしょうか?考えられる解決策は、各リクエストの応答ヘッダーの戻り値に基づいてトークンを継続的に更新すること以外の何ものでもありません。しかし、この方法はフロントエンド開発のビジネス層に侵入します。各インターフェイスはトークンを更新する必要があります。
これはインターセプターを追加するだけであり、ビジネスにあまり干渉しないと言う人もいるかもしれません。ロジックのこの部分はインターセプターで記述されていますが、トークン認証ロジックのため、フロントエンドにはこの余分なコードがあります。機能分業の観点から見ると、コードのこの部分は実際にはバックエンド ロジックです。
もっと簡単に言うと、トークンの更新とトークンの適時性の管理はバックエンドで行う必要があります。フロントエンドはロジックのこの部分を気にする必要はありませんし、気にする必要もありません。
要約すると、リフレッシュ トークンの有効期限はバックエンドに配置する必要があり、有効期限を判断することでトークンが有効であるかどうかを判断することはできません。 JWT のペイロード内。
したがって、ユーザーが正常にログインしてトークンをフロントエンドに返した後、一意の表現をキーとして、現在のトークンを値として使用して、トークンを Redis キャッシュに書き込む必要があります。各ユーザーのリクエストが成功すると、トークンの有効期限が更新されます。そのプロセスは次のとおりです。
#このように再構築すると、プロセスは次のようになります。 プロセス内でトークンを更新する追加のプロセスがあります。ユーザーがシステムにログインしている限り、操作ごとにトークンの有効期限が更新され、前述したように操作中の突然の障害によってデータが失われることはありません。 ユーザーがログインしてから 2 時間以内にユーザーが何も操作を実行しなかった場合、2 時間後に再度インターフェイスを要求すると、サーバーによってアクセスが直接拒否されます。4. 概要
一般的に、特に機密性の高い情報を JWT に含めることはお勧めできません。非対称暗号化アルゴリズムが使用されていない場合は、トークンをコピーした後、jwt 公式 Web サイトに直接アクセスしてオンラインで分析できます。リクエストが傍受された場合、そのリクエスト内のすべての情報は透過的になります。 ただし、JWT は、一定期間サーバー リソースにアクセスするための資格情報として使用できます。たとえば、JWT ペイロードに userId フィールドが含まれている場合、トークンによって識別されるユーザーの正当性を検証できます。たとえば、ユーザーは現在ロックアウトされていますか?この userId で識別されるユーザーはシステムに存在しますか?等そしてトークンを公開することで、ユーザーは複数の端末から同時にログインできるようになります。以前と同様にログイン後にトークンを作成すると、ユーザーは同時に 1 つのデバイスにのみログインできるように制限されます。以上がSpringBoot に JWT 認証を統合する方法 (コード付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。