Как создать токен аутентификации с помощью Java - программирование
Подтвердить что ты не робот

Как создать токен аутентификации с помощью Java

На моей службе Java EE6, REST я хочу использовать токены аутентификации для входа с мобильных устройств, Пользователь отправит свое имя пользователя, пароль, а сервер отправит обратно токен, который будет использоваться для авторизации пользователя по их дальнейшим запросам за определенное время.

Можно ли просто создать токен таким образом? (Я думаю, мне не нужно его шифровать, так как я буду использовать HTTPS.)

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

Или есть более стандартный способ создания моих токенов? возможно, он существует в одном из API

4b9b3361

Ответ 1

Схема, которую вы предлагаете, позволяет клиенту неограниченный доступ к вашей службе. После первоначального входа пользовательский идентификатор и "userid" будут доступны клиенту, которые могут быть просто объединены с всегда действующей меткой времени.

Если вам нужна служба с именем "login" и токеном сеанса, то почему бы просто не использовать HttpSession?

Ответ 2

Чтобы создать труднодоступный токен в Java, используйте java.security.SecureRandom

например.

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

Вместо того, чтобы включать имя пользователя в токен, было бы лучше кэшировать карту пользователя: маркер в памяти или в базе данных.  

Ответ 3

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);
}

}

Взято и значительно сокращено из fooobar.com/questions/934/...

Ответ 4

Существует способ создания токенов, которые не могут быть скомпрометированы, но могут также использоваться для аутентификации.

Создайте комбинированный токен:

base64 (username + expiration + другие значения для клиента + 3ds encoded (имя пользователя, срок действия, источник ip, идентификатор браузера, другие значения для клиента))

Клиент может использовать токен для аутентификации запроса, например, использование веб-маркера JSON (RFC 7515).

На стороне сервера ключи, которые используются для кодирования 3des, могут вращаться со временем, как токен. Каждый запрос содержит токен для аутентификации, и каждый ответ содержит тот же токен или новый до истечения срока действия.

В этом случае токен содержит имя пользователя, поэтому по запросу аутентификация требует только проверить, что закодированная часть 3des действительна или нет (то же самое, что и источник запроса ip такой же. В этом случае, если кто-то украл токен, токен более ограничен в качестве идентификатора сеанса. Вы можете составлять другие идентификаторы для токена, например, браузер и т.д. Сложнее подделывать запрос, потому что злоумышленнику приходится подделывать больше вещей - что неизвестно для него, потому что он не знает, что происходит закодированную часть токена. (На самом деле нет идеальной защиты, только можно усложнить процесс взлома)

Плюсы этого решения:

  • Каждая деталь стандартная, но не все вместе, и злоумышленник должен знать детали реализации, чтобы иметь возможность атаковать.
  • Клиентская сторона может использовать части маркера для отображения информации из токена, в то время как сам токен защищен, потому что каждая незашифрованная часть содержится в зашифрованной части - поэтому ее нельзя изменить без признания недействительности маркера на стороне сервера, поэтому его легко для обнаружения атаки.
  • Для кластеризации нет необходимости в репликации сеанса/липких сеансах. Ключи 3des достаточно для репликации между узлами - поэтому он подходит для бэкэнд-стратегии без состояния.

Концы

  • Сложнее реализовать на стороне сервера, потому что для этого решения необходимо реализовать алгоритм генерации/проверки маркера на стороне сервера. Рекомендуется использовать этот фильтр сервера.

  • Клиенты должны реализовать хранилище токенов - вместо того, чтобы использовать хранилище сеансов браузера cookie, - проще украсть файлы cookie.

  • Обязательно убедитесь, что ключи 3des обеспечены достаточно - рекомендуется использовать защиту Java, чтобы избежать исключения.

Ответ 5

Для 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);
}

Выше код будет генерировать случайную строку в кодировке base64 с 32 символами. В кодировке Base64 каждый символ кодирует 6 бит данных. Таким образом, за 24 байта из приведенного выше примера вы получите 32 символа. Вы можете изменить длину выходной строки, изменив количество случайных байтов. Это решение является более безопасным, чем UUID (который использует только 16 случайных байтов), и генерирует строку, которую можно безопасно использовать в HTTP-URL.

Ответ 6

REST основан на HTTP и рекомендует использовать базовый протокол, а не изобретать колесо. HTTP использует файлы cookie для поддержки взаимодействий с состоянием, таких как запоминание подлинности, а также поддерживает аутентификацию имени пользователя и пароля.

Кроме того, Java EE поддерживает все это из коробки. Проверьте учебное пособие

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