Подтвердить что ты не робот

Создание криптографически защищенных токенов аутентификации

Фон:

Это действительно общий вопрос, связанный с лучшей практикой, но может быть полезно некоторое описание конкретной ситуации:

Мы разрабатываем "подключенное" приложение для iPhone. Он будет связываться с бэкэнд-приложением через службы REST. Чтобы не запрашивать у пользователя имя пользователя и пароль при каждом запуске приложения, мы откроем службу "Логин", которая проверяет их имя пользователя и пароль при первом запуске и возвращает токен аутентификации, который может быть использован для будущей сети запросы на обслуживание для реальных данных. У токена может быть срок действия, после которого мы попросим их повторно аутентифицироваться с их именем пользователя/паролем.

Вопрос:

Каковы наилучшие методы для создания такого токена, который будет использоваться для аутентификации?

Например, мы могли бы...

  • Hash (SHA-256 и т.д.) - случайная строка и сохранить ее в базе данных для данного пользователя вместе с датой истечения срока действия. Сделайте простой поиск токена в последующих запросах, чтобы убедиться, что он соответствует.
  • Зашифруйте идентификатор пользователя и некоторую дополнительную информацию (временную метку и т.д.) с помощью секретного ключа. Расшифруйте токен в последующих запросах, чтобы убедиться, что он был выпущен нами.

Похоже, что это должна быть проблема.

4b9b3361

Ответ 1

Основываясь на отзывах других ответов на этот вопрос, дополнительных исследованиях и обсуждениях в оффлайне, вот что мы в итоге сделали...

Было отмечено довольно быстро, что модель взаимодействия здесь по существу точно такая же, как модель, используемая в Autodesk Forms в ASP.NET, когда установлен флажок "помнить меня". Это просто не веб-браузер, делающий HTTP-запросы. Наш "билет" эквивалентен файлу cookie, который формирует комплекты аутентификации. Аутентификация форм использует по умолчанию "зашифровать некоторые данные с помощью секретного ключа" по умолчанию.

В нашей веб-службе входа мы используем этот код для создания билета:

string[] userData = new string[4];

// fill the userData array with the information we need for subsequent requests
userData[0] = ...; // data we need
userData[1] = ...; // other data, etc

// create a Forms Auth ticket with the username and the user data. 
FormsAuthenticationTicket formsTicket = new FormsAuthenticationTicket(
    1,
    username,
    DateTime.Now,
    DateTime.Now.AddMinutes(DefaultTimeout),
    true,
    string.Join(UserDataDelimiter, userData)
    );

// encrypt the ticket
string encryptedTicket = FormsAuthentication.Encrypt(formsTicket);

Затем у нас есть атрибут поведения операции для служб WCF, который добавляет IParameterInspector, который проверяет действительный билет в заголовках HTTP для запроса. Разработчики помещают этот атрибут поведения операции в операции, требующие аутентификации. Вот как этот код анализирует билет:

// get the Forms Auth ticket object back from the encrypted Ticket
FormsAuthenticationTicket formsTicket = FormsAuthentication.Decrypt(encryptedTicket);

// split the user data back apart
string[] userData = formsTicket.UserData.Split(new string[] { UserDataDelimiter }, StringSplitOptions.None);

// verify that the username in the ticket matches the username that was sent with the request
if (formsTicket.Name == expectedUsername)
{
    // ticket is valid
    ...
}

Ответ 2

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

Если вы склонны строить свой собственный "истекающий билет из системы входа в систему", а не повторно использовать существующий, вероятно, хорошая идея, по крайней мере, ознакомиться с проблемами, которые привели к разработке подобных систем, как и Kerberos. Нежное введение здесь:

http://web.mit.edu/kerberos/dialogue.html

Также было бы неплохо взглянуть на то, какие дыры в безопасности были обнаружены в Kerberos (и аналогичных системах) за последние 20 лет, и убедитесь, что вы их не реплицируете. Kerberos был создан экспертами по безопасности и тщательно анализируется на протяжении десятилетий, и в нем все еще встречаются серьезные алгоритмические недостатки:

http://web.mit.edu/kerberos/www/advisories/MITKRB5-SA-2003-004-krb4.txt

Гораздо лучше учиться на своих ошибках, чем ваши собственные.

Ответ 3

Amazon.com использует токен сообщения HMAC SHA-1 для аутентификации и авторизации запросов. Они используют это для довольно большой коммерческой службы, поэтому я буду доверять их инженерным решениям. Google публикует OpenSocial API, который несколько похож. Основываясь на Google и Amazon.com, используя похожие и открыто опубликованные подходы к защите веб-запросов, я подозреваю, что это, вероятно, хорошие способы.

Ответ 4

Любой из двух ответов, которые вы предоставили, будет достаточным. Вы можете найти фреймворки, которые делают это для вас, но, правда, это не так сложно построить. (Каждая компания, с которой я работала, уже переделала.) Выбор данных, хранящихся в базе данных, в сравнении с зашифрованными данными "cookie" - это архитектурное решение - вы хотите, чтобы поиск в базе данных просматривался на каждом просмотре страницы, или вы бы предпочли пережевывать процессор с расшифровкой файлов cookie? В большинстве приложений использование зашифрованных файлов cookie обеспечивает выигрыш в производительности по шкале (если это связано). В противном случае это просто вопрос вкуса.

Ответ 5

Поскольку вы используете WCF, у вас есть множество опций, если вы используете CFNetwork - например, NTLM или Digest Authentication:

http://developer.apple.com/documentation/Networking/Conceptual/CFNetwork/Concepts/Concepts.html#//apple_ref/doc/uid/TP30001132-CH4-SW7

Я знаю, что это не отвечает на ваш конкретный вопрос, но я также столкнулся с этой проблемой (iPhone - Tomcat) и решил как можно больше использовать службы аутентификации на веб-сервере. В большинстве случаев нет существенного штрафа за включение информации аутентификации с каждым запросом. Быстрый Google раскрывает множество сообщений в блогах о службах WCF и RESTful (и некоторые связанные с ними вопросы по StackOverflow).

Надеюсь, это поможет!

Ответ 6

Вы должны реализовать:

которые являются именно рабочими потоками, от OAuth2, которые вы ищете. Не изобретайте велосипед.

Ответ 7

Это просто звучит как идентификатор сеанса с длительным сроком действия. Те же принципы, которые использовались для этого в веб-приложениях, могут применяться здесь.

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

Безопасность зависит от непредсказуемости идентификаторов сеанса. Создайте их с криптографическим RNG, из очень большого пространства.