web-dev-qa-db-ja.com

Javaを使用して認証トークンを作成する方法

私のJava EE6、REST=サービス、モバイルデバイスからのログインに認証トークンを使用したい。ユーザーはユーザー名、パスワードを送信し、サーバーは送信するトークン。これは、指定された期間のユーザーの以降のリクエストを許可するために使用されます。

このようなトークンを自分で作成することはできますか?(HTTPSを使用するため、これを暗号化する必要はないと思います。)

String token = UUID.randomUUID().toString().toUpperCase() 
            + "|" + "userid" + "|"
            + cal.getTimeInMillis();

または、トークンを作成するより標準的な方法がありますか?多分それはAPIの1つに存在します

22
Spring

提案しているスキームにより、クライアントはサービスに無制限にアクセスできます。最初のログイン後、UIDと「userid」がクライアントで利用可能になり、常に有効なタイムスタンプと簡単に組み合わせることができます。

「ログイン」とセッショントークンを使用するサービスが必要な場合は、なぜHttpSessionを使用しないのですか?

8
ireddick

推測しにくいトークンをJavaで使用するにはJava.security.SecureRandom

例えば。

SecureRandom random = new SecureRandom();
byte bytes[] = new byte[20];
random.nextBytes(bytes);
String token = bytes.toString();

トークンにユーザー名を含めるよりも、ユーザーまたはトークンマップをメモリまたはデータベースにキャッシュする方が適切です。

14
Daniel de Zwaan

Java 8以上の場合、最速かつ最も簡単なソリューションは次のとおりです。

private static final SecureRandom secureRandom = new SecureRandom(); //threadsafe
private static final Base64.Encoder base64Encoder = Base64.getUrlEncoder(); //threadsafe

public static String generateNewToken() {
    byte[] randomBytes = new byte[24];
    secureRandom.nextBytes(randomBytes);
    return base64Encoder.encodeToString(randomBytes);
}

出力例:

wrYl_zl_8dLXaZul7GcfpqmDqr7jEnli
7or_zct_ETxJnOa4ddaEzftNXbuvNSB-
CkZss7TdsTVHRHfqBMq_HqQUxBGCTgWj
8loHzi27gJTO1xTqTd9SkJGYP8rYlNQn

上記のコードは、32文字のbase64エンコーディングでランダムな文字列を生成します。 Base64エンコードでは、すべての文字がデータの6ビットをエンコードします。したがって、上記の例の24バイトでは、32文字が取得されます。ランダムバイト数を変更することにより、出力文字列の長さを変更できます。このソリューションは、UUID(16バイトのランダムバイトのみを使用)よりも安全であり、HTTP URLで安全に使用できる文字列を生成します。

7

RESTはHTTPに基づいており、車輪を再発明するのではなく、基礎となるプロトコルの使用を推奨します。 HTTPは、Cookieを使用して、認証の記憶などのステートフルな対話をサポートし、ユーザー名とパスワードの認証もサポートします。

さらに、Java EEはこれらすべてをすぐにサポートします。チュートリアルを確認してください。

http://docs.Oracle.com/javaee/6/tutorial/doc/bncas.html

0
artbristol

トークンを作成する方法はありますが、これは妥協することはできませんが、認証にも使用できます。

結合されるトークンを作成します。

base64(username + expiration + clientの他の値+ 3des encoded(usename、expiration、source ip、browser identitifier、other other values for client))

クライアントは、JSON Web Token(RFC 7515)の使用など、トークンを使用してリクエストを認証できます。

サーバー側では、トークンとして3desエンコーディングに使用されるキーを時間とともに回転させることができます。すべてのリクエストには認証用のトークンが含まれ、すべてのレスポンスには有効期限前の同じトークンまたは新しいトークンが含まれます。

その場合、トークンにはユーザー名が含まれるため、リクエスト認証では3desエンコードされた部分が有効かどうかを確認するだけで済みます(と同じ、リクエストipのソースは同じです。この場合、誰かがトークンを盗んだ場合、トークンの使いやすさはブラウザIDなど、トークンに他の識別子を作成できます。攻撃者はさらに多くのものを偽造する必要があるため、リクエストを偽造するのが難しくなります-エンコードされた部分に何があるかわからないため、攻撃者にとっては不明ですトークン(実際のところ、完璧なセキュリティは存在せず、クラックをより困難にすることができます)

このソリューションの長所は次のとおりです。

  • すべての要素は標準ですが、全体ではなく、攻撃者は実装の詳細を知ってから攻撃する必要があります。
  • 暗号化されていない部分はすべて暗号化された部分に含まれているため、クライアント側はトークンの一部を使用してトークンから情報を表示できます。したがって、サーバー側でトークンを無効にしないと変更できません。攻撃。
  • クラスタリングのためにセッション複製/スティッキーセッションの必要はありません。ノード間で複製するのに十分な3desキー-ステートレスバックエンド戦略に適しています。

短所は

  • このソリューションでは、サーバー側でトークン生成/検証アルゴリズムを実装する必要があるため、サーバー側での実装が困難です。そのサーバーフィルターの使用をお勧めします。

  • クライアントは、Cookieブラウザセッションストアの代わりにトークンストアを実装する必要があります-Cookieを盗むのが簡単です。

  • 3desキーが十分に保護されていることを確認する必要があります-Javaセキュリティは、妥協を避けるために使用することをお勧めします。
0
public class SecureTokenGenerator {
public static final String CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

// 2048 bit keys should be secure until 2030 - https://web.archive.org/web/20170417095741/https://www.emc.com/emc-plus/rsa-labs/historical/twirl-and-rsa-key-size.htm
public static final int SECURE_TOKEN_LENGTH = 256;

private static final SecureRandom random = new SecureRandom();

private static final char[] symbols = CHARACTERS.toCharArray();

private static final char[] buf = new char[SECURE_TOKEN_LENGTH];

/**
 * Generate the next secure random token in the series.
 */
public static String nextToken() {
    for (int idx = 0; idx < buf.length; ++idx)
        buf[idx] = symbols[random.nextInt(symbols.length)];
    return new String(buf);
}

}

https://stackoverflow.com/a/41156/584947 から取得して大幅に凝縮

0
anon58192932