JWTベースのトークン認証の詳細な説明(Java実装)

JWTベースのトークン認証の詳細な説明(Java実装)

表示する前のヒント:

この記事で使用されているIDEAバージョンは究極の2019.1であり、JDKバージョンは1.8.0_141です。

1はじめに

コンピュータID認証では、トークン(一時的)を意味します。実際、トークンの方が一般的であり、シークレットコードと呼ぶことができます。データ送信の前に、シークレットコードを最初にチェックする必要があります。さまざまなデータ操作に対してさまざまなシークレットコードが許可されます。

2.JWT

JSON Webトークン、JSON Webトークン、次の例もJWTによって実装されたトークン認証に基づいています。以下は、完成したJWT文字列です。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODMyOTQxNzEsInVzZXJOYW1lIjoidXNlciIsInBhc3N3b3JkIjoiMTExMTExMTEifQ.t6JLktclylpt2s5T_B1KDxYCJALr-fbZsy1J_YT57Jk

ヘッダー、ペイロード、署名の3つの部分で構成されています

2.1ヘッダー

2つの部分で構成されます

  1. 宣言タイプはJWTです。

  2. 暗号化アルゴリズムを宣言し、HMACSHA256を使用します

以下に示すように、JWTヘッダー部分はJSONオブジェクトです。

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

Base64で暗号化すると、JWTが最初の部分を構成します。

2.2ペイロード

ペイロード部分はJWTのメインコンテンツ部分であり、3つの部分で構成されるJSONオブジェクトでもあります。

  1. 標準に登録された宣言

  2. 公式声明

  3. プライベートステートメント

標準に登録されている宣言には、7つのデフォルトフィールドがあります。

  1. iss:発行者

  2. exp:有効期限

  3. サブ:件名

  4. aud:ユーザー

  5. nbf:以前は利用できません

  6. iat:リリース時間

  7. jti:JWTIDはJWTを識別するために使用されます

公式声明

公式声明では、あらゆる情報を追加できます。通常、ユーザー関連情報やビジネスに必要なその他の必要な情報を追加します(機密情報は推奨されません)。

プライベートステートメント

プライベートステートメントは、プロバイダーとコンシューマーが共同で定義するステートメントです(機密情報は推奨されません)。

次の例はサンプルペイロードです

{
	"sub": "1234567890",
	"name": "userName",
	"admin": true
}

Base64で暗号化して、JWTの2番目の部分を形成します。

注:JWTはデフォルトで暗号化されておらず、誰でもその内容を解釈できます。したがって、情報漏えいを防ぐために、個人情報フィールドを作成したり、機密情報を保存したりしないでください。

2.3署名

署名ハッシュ部分は、データの上記2つの部分に署名し、指定されたアルゴリズムを使用してハッシュを生成し、データが改ざんされないようにします。これは3つの部分で構成されています。

  1. ヘッダー(Base64で暗号化)

  2. ペイロード(Base64暗号化)

  3. 秘密

サーバーには秘密鍵が必要です。秘密鍵はサーバーにのみ保存され、ユーザーに開示することはできません。次に、ヘッダーで指定された署名アルゴリズム(デフォルトではHMAC SHA256)を使用して、次の式に従って署名を生成します。

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

署名ハッシュが計算された後、JWTヘッダー、ペイロード、および署名ハッシュの3つの部分が結合されて文字列になり、各部分が「。」で区切られてJWTオブジェクト全体が形成されます。

3.使用する

クライアントは、サーバーから返されたJWTを受信し、CookieまたはlocalStorageに保存します。

その後、クライアントはサーバーと対話するときにJWTをもたらします。Cookieに保存されている場合は、自動的に送信できますが、ドメインをまたがることはないため、通常、HTTPリクエストのHeaderAuthorizationフィールドに入力されます。

次の形式を使用します

Authorization: Bearer JWT

JWTインタラクションのプロセス全体を次の図に示します。

ここに写真の説明を挿入

4.例

この例では、JWT署名と検証を実装するためのJavaのみを提供しており、http送信の使用は後で追加されます。

pom.xmlが参照する必要があるjarパッケージ

<dependency>
      <groupId>com.auth0</groupId>
      <artifactId>java-jwt</artifactId>
      <version>3.10.0</version>
    </dependency>

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.10.2</version>
    </dependency>

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.10.2</version>
    </dependency>

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.10.2</version>
    </dependency>

ツールクラスTokenUtil.java

package token;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class TokenUtil {
    
    

    //token过期时长30分钟
    private static final long EXPIRE_TIME = 30 * 60 * 1000;
    //token私钥
    private static final String TOKEN_SECRET = "abcdefg";

    public static String sign(String userName, String password) {
    
    

        String signData = "";
        //过期时间
        Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
        //私钥及加密算法
        Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
        //设置头信息
        Map<String, Object> header = new HashMap();
        header.put("typ", "JWT");
        header.put("alg", "HS256");

        signData = JWT.create()
                .withHeader(header)
                .withClaim("userName", userName)
                .withClaim("password", password)
                .withExpiresAt(date)
                .sign(algorithm);

        return signData;
    }

    /**
     * @Description token解码校验
     * @param token
     * @return
     * @Create 2020-03-03 by jjy
     */
    public static boolean verfiy(String token) {
    
    

        try {
    
    
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            JWTVerifier jwtVerifier = JWT.require(algorithm).build();
            DecodedJWT decodedJWT = jwtVerifier.verify(token);
            String userName = decodedJWT.getClaim("userName").asString();
            String password = decodedJWT.getClaim("password").asString();
            if(!Test.USERNAME.equals(userName) || !Test.PASSWORD.equals(password)) {
    
    
                return false;
            }
            if(new Date().getTime() > decodedJWT.getExpiresAt().getTime()){
    
    
                return false;
            }
            
        } catch (Exception e) {
    
    
            return false;
        }

        return true;
    }
}

テストクラスTest.java

package token;

public class Test {
    
    

    public static final String USERNAME = "user";
    public static final String PASSWORD = "11111111";

    public static void main(String[] args) {
    
    
        String token = TokenUtil.sign(USERNAME, PASSWORD);

        System.out.println("加密后的token为:" + token);

        boolean flag = TokenUtil.verfiy(token);

        if(flag){
    
    
            System.out.println("校验成功");
        } else {
    
    
            System.out.println("校验失败");
        }
    }
}

結果は以下のとおりです。

ここに写真の説明を挿入

おすすめ

転載: blog.csdn.net/weixin_43611145/article/details/104649851