36

私のJavaEE6、RESTサービスでは、モバイルデバイスからのログインに認証トークンを使用したいのですが、ユーザーはユーザー名とパスワードを送信し、サーバーはトークンを送り返します。トークンは、特定のユーザーに対する追加のリクエストでユーザーを承認するために使用されます。時間。

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

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

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

4

7 に答える 7

41

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文字が得られます。ランダムなバイト数を変更することにより、出力文字列の長さを変更できます。このソリューションは(ランダムな16バイトのみを使用する)よりも安全でUUIDあり、HTTPURLで安全に使用できる文字列を生成します。

于 2019-06-17T09:23:01.260 に答える
17

Javaで推測しにくいトークンを作成するには、java.security.SecureRandom

例えば

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

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

于 2015-06-11T03:47:48.643 に答える
9

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

'login'とセッショントークンを備えたサービスが必要な場合は、HttpSessionを使用しないのはなぜですか?

于 2012-12-21T16:37:34.823 に答える
1

侵害されることはないが、認証にも使用できるトークンを作成する方法があります。

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

base64(ユーザー名+有効期限+クライアントのその他の値+ 3desエンコード(usename、expiration、source ip、ブラウザーID、クライアントのその他の値))

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

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

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

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

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

短所は

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

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

  • 3desキーが十分に保護されていることを確認する必要があります-妥協を避けるためにJavaセキュリティを使用することをお勧めします。
于 2017-02-05T10:31:13.060 に答える
1
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から取得し、大幅に凝縮

于 2018-01-16T16:18:41.883 に答える
1

一意のトークンを作成します。これは、ロジックと使用したパラメーターの数に完全に基づいています。Java 8Supplierの機能インターフェイスは、次のことに役立ちます。

Supplier<String> tokenSupplier = () -> {

        StringBuilder token = new StringBuilder();
        long currentTimeInMilisecond = Instant.now().toEpochMilli();
        return token.append(currentTimeInMilisecond).append("-")
                .append(UUID.randomUUID().toString()).toString();
};

System.out.println(tokenSupplier.get());

出力:

1591457374665-d5eff25f-b083-41c3-a90d-a89adcc45043

あなたはここでそれについてもっと学ぶことができます-Javaトークン

于 2020-06-06T16:18:37.950 に答える
-3

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

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

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

于 2012-12-21T16:14:41.070 に答える