私のJava EE6、REST=サービス、モバイルデバイスからのログインに認証トークンを使用したい。ユーザーはユーザー名、パスワードを送信し、サーバーは送信するトークン。これは、指定された期間のユーザーの以降のリクエストを許可するために使用されます。
このようなトークンを自分で作成することはできますか?(HTTPSを使用するため、これを暗号化する必要はないと思います。)
String token = UUID.randomUUID().toString().toUpperCase()
+ "|" + "userid" + "|"
+ cal.getTimeInMillis();
または、トークンを作成するより標準的な方法がありますか?多分それはAPIの1つに存在します
提案しているスキームにより、クライアントはサービスに無制限にアクセスできます。最初のログイン後、UIDと「userid」がクライアントで利用可能になり、常に有効なタイムスタンプと簡単に組み合わせることができます。
「ログイン」とセッショントークンを使用するサービスが必要な場合は、なぜHttpSessionを使用しないのですか?
推測しにくいトークンをJavaで使用するにはJava.security.SecureRandom
例えば。
SecureRandom random = new SecureRandom();
byte bytes[] = new byte[20];
random.nextBytes(bytes);
String token = bytes.toString();
トークンにユーザー名を含めるよりも、ユーザーまたはトークンマップをメモリまたはデータベースにキャッシュする方が適切です。
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で安全に使用できる文字列を生成します。
RESTはHTTPに基づいており、車輪を再発明するのではなく、基礎となるプロトコルの使用を推奨します。 HTTPは、Cookieを使用して、認証の記憶などのステートフルな対話をサポートし、ユーザー名とパスワードの認証もサポートします。
さらに、Java EEはこれらすべてをすぐにサポートします。チュートリアルを確認してください。
トークンを作成する方法はありますが、これは妥協することはできませんが、認証にも使用できます。
結合されるトークンを作成します。
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など、トークンに他の識別子を作成できます。攻撃者はさらに多くのものを偽造する必要があるため、リクエストを偽造するのが難しくなります-エンコードされた部分に何があるかわからないため、攻撃者にとっては不明ですトークン(実際のところ、完璧なセキュリティは存在せず、クラックをより困難にすることができます)
このソリューションの長所は次のとおりです。
短所は
このソリューションでは、サーバー側でトークン生成/検証アルゴリズムを実装する必要があるため、サーバー側での実装が困難です。そのサーバーフィルターの使用をお勧めします。
クライアントは、Cookieブラウザセッションストアの代わりにトークンストアを実装する必要があります-Cookieを盗むのが簡単です。
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 から取得して大幅に凝縮