JWT の認証と認可を実装する方法をステップごとに説明します



序文

このブロガーは CSDN を使用して、ソフトウェア開発の学習中に個人的に得たり学んだ経験や知識を記録します。興味のある友人はブロガーに注目してください。
おそらく、人は一人でも速く進むことができますが、グループではさらに遠くまで進むことができます。

1. はじめに

前回の記事ではトークン(token)認証という認証の仕組みを紹介しましたが、今回はJWT認証(JSON Web Token認証)についてご紹介します。

2. トークン認証とJWT認証の関係

プレッシャーを感じていますか? Cookie 認証、セッション認証だけでなく、トークン認証、さらには JWT 認証も学びました。心配しないでください。この JWT 認証は新しい認証方法ではありません。トークンベースの認証メカニズム。トークン認証は一般的な認証方法です。認証にはさまざまなタイプのトークンを使用できます。JWT はトークン タイプの 1 つです。

前の記事で紹介したトークン認証メカニズムは、認証にさまざまな種類のトークンを使用する方法をカバーする広い概念および一般用語です。JWT 以外にも、時間ベースのトークン (Time-based Token) やアクセス トークン (Access Token) など、他の種類のトークンがあります。これらのトークンはさまざまな形式と認証メカニズムを使用できますが、それらはすべてユーザーを認証し、保護されたリソースへのアクセスを許可するために使用される資格情報です。

ということで、関係性を明確にしてから本文を入力しましょう!

3. JWT認証とは何ですか?

JWT 認証 (JSON Web トークン認証) は、トークンベースの認証メカニズムです。JSON Web Token (JWT) を認証資格情報として使用し、JWT を検証することでユーザーの ID を確認し、保護されたリソースへのユーザーのアクセスを許可します。

4. JWTの構成

上で述べたように、JWT は多くのトークン タイプの 1 つにすぎないため、その構成が私たちの研究の焦点です。

JWT は、情報を表現および送信するためのコンパクトで自己完結型の方法を定義するオープン スタンダード (RFC 7519) です。これは 3 つの部分で構成されます。

  1. ヘッダー: 使用される署名アルゴリズムなど、JWT を説明するメタデータとアルゴリズム情報が含まれます。
  2. ペイロード: JWT によって宣言されたデータが含まれます。これには、ユーザー ID 情報、認可情報、その他のカスタム データを含めることができます。
  3. Signature : データの整合性と検証のために、キーと指定された署名アルゴリズムを使用してヘッダーとペイロードに署名します。

ここに画像の説明を挿入

1. ヘッダー

ヘッダーには通常、トークン タイプ (typ) と署名アルゴリズム (alg) の 2 つの部分が含まれます。この情報は、使用される JWT のタイプと暗号化アルゴリズムを記述するために使用されます。たとえば、一般的なヘッダーは次の JSON 形式になります。

{
  "alg": "HS256",
  "typ": "JWT"
}

上記の例では、「alg」は署名アルゴリズムがHMAC SHA-256(HS256)であることを示し、「typ」はトークンタイプがJWTであることを示します。

2.ペイロード

ペイロードは JWT の本体であり、送信されるデータが含まれます。ペイロードには、いくつかの事前定義されたクレーム (クレーム) を含めることができ、またカスタム クレームを含めることもできます。事前定義された宣言は、次の 3 つのカテゴリに分類されます。

  • 登録済みクレーム: これらのクレームは、iss (発行者)、sub (件名)、aud (対象者)、exp (有効期限)、nbf (有効時間)、iat (発行時間) などを含む、事前定義された標準クレームのセットです。
  • パブリック クレーム: これらのクレームはユーザーが自由に定義できる自己定義クレームですが、競合を避けるために特定の命名規則に従うことをお勧めします。
    プライベート クレーム: これらのクレームもカスタム クレームですが、競合を避けるために、「company_name」などの名前空間の形式で名前を付けることをお勧めします。
    以下はペイロードの例の JSON 形式です。
{
  "sub": "user123",
  "name": "John Doe",
  "iat": 1629012345
}

上記の例では、「sub」は件名が「user123」であるユーザーを意味し、「name」はユーザー名が「John Doe」であることを意味し、「iat」は JWT が 1629012345 (UNIX タイムスタンプ) に発行されたことを意味します。

3. 署名

署名は JWT の 3 番目の部分であり、JWT の整合性と信頼性を検証するために使用されます。署名は通常、ヘッダーとペイロードのデータと秘密鍵を使用して生成されます。署名を生成するプロセスでは、ヘッダーとペイロードをエンコードし、指定された署名アルゴリズム (HMAC、RSA など) を使用して暗号化します。結果の署名文字列が JWT の末尾に追加されます。

署名の例:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secretKey
)

上記の例では、「header」はヘッダーの Base64 エンコード文字列、「payload」はペイロードの Base64 エンコード文字列、「secretKey」は署名の生成に使用される秘密鍵を示します。

完全な JWT は、次の 3 つの部分をピリオド (.) で連結することによって形成されます。

base64UrlEncode(header) + "." +
base64UrlEncode(payload) + "." +
signature

最終的な JWT は認証資格情報としてクライアントとサーバー間で送信でき、署名を検証することで JWT の信頼性と完全性を検証できます。

もちろん、このトークンの安全性を疑問視する人も多いでしょう。JWT はドット ヘッダー、ペイロード、署名で区切られた 3 つの部分で構成されています

  1. ヘッダー部分は、署名の生成にどのアルゴリズムを使用する必要があるかを宣言します。

  2. ペイロード部分は有効期間などの特定のデータです。

  3. 次に、ヘッダーとペイロードのコンテンツは BASE64 によってエンコードされます。これは暗号化ではなくエンコードであることに注意してください。つまり、簡単にデコードできます。JWT はサーバーに保存されませんが、サーバーはパスワードを保存する必要があります。このパスワードは 2 つのエンコードと組み合わせる必要があり、アルゴリズム操作を実行して最終的に署名情報を取得します。ここで使用されるアルゴリズムは、ヘッダーで宣言されたばかりのアルゴリズムです。署名された情報、つまり署名部分。完全かつ最大の JWT をクライアントに送信できます。3 つの部分、文字の 1 つ、JWT 全体の最大値を変更すると、3 つの部分は関連しているため、JWT には一定のセキュリティが確保されます。

引用ですが先生
トークンはサーバーによって暗号化されたユーザー情報であり、サーバーはトークンをブラウザーに送信し、ブラウザーは Cookie またはストレージを使用して Cookie を保存します。その後、ブラウザはリクエストを送信するたびにトークンを取得し、サーバーはトークンを復号してユーザーのログインを確認します。

5、JWT認証ワークフロー

JWT 認証のワークフローには通常、次の手順が含まれます。

  1. ユーザー認証:
    ユーザーが認証するとき、通常、ユーザーを識別する資格情報 (ユーザー名やパスワードなど) が提供されます。サーバーは、通常、データベースに保存されているユーザーの資格情報と比較することによって、これらの資格情報の有効性を検証する必要があります。

  2. JWT の生成:
    ユーザーが認証されると、サーバーは認証資格情報として JWT を生成します。JWT を生成するプロセスは次の手順で構成されます。

    • ヘッダーとペイロードを含む JSON オブジェクトを作成します。
    • ヘッダーとペイロードを Base64 エンコードして、JWT の最初の部分を生成します。
    • サーバー上のキーと指定された署名アルゴリズムを使用して、エンコードされたヘッダーとペイロードに署名し、署名を生成します。
    • 署名をエンコードされたヘッダーおよびペイロードと連結して、完全な JWT を生成します。
  3. JWT の送信と保存:
    サーバーは、通常、応答の一部として (たとえば、HTTP 応答のヘッダーまたは応答の一部として) JWT を返すことによって、生成された JWT をクライアントに送信します。通常、クライアントは JWT をブラウザのローカル ストレージやメモリなどのローカルに保存します。

  4. 後続のリクエストの認証:
    後続のリクエストでは、クライアントは認証資格情報として JWT をサーバーに送信します。これは通常、JWT をリクエスト ヘッダー (Authorization ヘッダーなど) に配置するか、リクエスト パラメーター (クエリ文字列やフォーム データなど) の一部としてサーバーに送信することによって行われます。

  5. JWT の検証と解析:
    リクエストを受信した後、サーバーは JWT の有効性と整合性を検証し、JWT 内の情報を解析する必要があります。検証と解析のプロセスには次の手順が含まれます。

    • リクエストから JWT を取得します。
    • JWT の署名が有効であることを確認して、JWT が改ざんされていないことを確認します。
    • JWT のヘッダーとペイロードをデコードして、JWT 内の情報を取得します。
  6. ユーザーの承認と保護されたリソースへのアクセス:
    サーバーは、JWT の有効性を検証し、JWT 内のユーザーの ID 情報を取得することで、ユーザーの ID を確認します。サーバーは、ユーザーの識別情報に基づいて、ユーザーが要求されたリソースにアクセスする権利を持っているかどうかを判断するための認可判断を行うことができます。ユーザーがリソースへのアクセスを許可されている場合、サーバーは対応するデータを返すか、対応する操作を実行します。

JWT 認証ワークフロー全体はステートレスに基づいており、サーバーはバックエンドにセッ​​ション状態を保存する必要がなく、各リクエストは独立しています。JWT は認証資格情報として機能し、ユーザーを認証し、保護されたリソースへのアクセスを許可するためのシンプルで安全かつスケーラブルな方法を提供します。

ここに画像の説明を挿入

6. コード例

Java JWT ライブラリ (jjwt) を使用したサンプル コードを次に示します。

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;

public class JWTExample {
     
     
    private static final String SECRET_KEY = "yourSecretKey";
    private static final long EXPIRATION_TIME = 86400000; // 24小时

    public static void main(String[] args) {
     
     
        // 创建JWT
        String token = createJWT("user123");

        // 验证和解析JWT
        if (validateJWT(token)) {
     
     
            String username = parseJWT(token);
            System.out.println("解析到的用户名:" + username);
        } else {
     
     
            System.out.println("JWT验证失败");
        }
    }

    public static String createJWT(String username) {
     
     
        Date now = new Date();
        Date expiration = new Date(now.getTime() + EXPIRATION_TIME);

        String token = Jwts.builder()
                .setSubject(username)
                .setIssuedAt(now)
                .setExpiration(expiration)
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();

        return token;
    }

    public static boolean validateJWT(String token) {
     
     
        try {
     
     
            Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token);
            return true;
        } catch (Exception e) {
     
     
            return false;
        }
    }

    public static String parseJWT(String token) {
     
     
        Jws<Claims> claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token);
        return claims.getBody().getSubject();
    }
}

上記の例では、このcreateJWTメソッドを使用してユーザー名、発行時刻、有効期限が設定された JWT を作成し、署名には HS256 アルゴリズムが使用されます。validateJWTこの方法は、JWT の正当性を検証するために使用され、JWT の署名を解析して検証することで判断します。parseJWTこのメソッドは、JWT を解析し、その中のユーザー名情報を抽出するために使用されます。

上記のコードのキーはSECRET_KEYJWT の署名と検証に使用されることに注意してください。必ず実際のキーに置き換えて安全に保管してください。さらに、この例で設定されている有効期限は 24 時間 (86400000 ミリ秒) ですが、必要に応じて調整できます。

このサンプル コードを使用すると、ユーザー名情報を含む JWT を作成し、JWT を検証および解析して内部のユーザー名を取得できます。

7. まとめ

3 つを複雑にしすぎないでください

  1. セッションはサーバー側で生成および保存され、サーバーがすべてを支配します。
  2. Cookie は一種のデータキャリアであり、Cookie にセッションを入れてクライアント側に送信します。Cookie は HTTP のリクエストごとに送信されます。
  3. トークンはサーバー上で生成されますが、ブラウザ側に保存されます。クライアントがすべてを支配します。トークンは Cookie またはストレージに配置できます。トークンを保持することは、トークンを保持するのと同様であり、サーバーへのアクセスを許可します。
  4. サーバーの検証は前提条件です。Cookie はクライアントに保存されますが、サーバーによって暗号化されません。セッションはクライアントに保存されますが、サーバーによって暗号化されて保存されます。トークンはクライアントに保存されますが、暗号化されてサーバーによって保存されません。
  5. セッションはユーザー ID とステータス情報を保存および管理するためのサーバー側のメカニズムであり、Cookie はクライアント側でセッション ID およびその他のデータを保存するためのメカニズムです。トークンは、ステートレス資格情報として送信できる軽量の認証および認可メカニズムです。Cookie とトークンの両方を使用して、クライアントとサーバーの間で ID 情報とステータス情報を転送し、認証とステータス管理の機能を実現できます。

おすすめ

転載: blog.csdn.net/weixin_52533007/article/details/132110578