Вопрос

У меня есть приложение, которое взаимодействует с сервером, использующим аутентификацию HTTP Digest.

Мне кажется, что управление "сеансами" в iPhone - это довольно "черный ящик" для нас, разработчиков.Правда ли, что мы не можем видеть, как фреймворк обрабатывает / сохраняет http-сеансы?

Если я здесь просто туплю, не мог бы кто-нибудь объяснить, как, вероятно, обрабатывать аутентификацию HTTP Digest на iPhone?

Мой основной прогон заключается в следующем:

  • Сделайте запрос на защищенный URL-адрес
  • Сервер отправляет 401
  • клиент создает и сохраняет учетные данные и передает их обратно серверу
  • сервер проверяет учетные данные, завершает запрос, если он подтвержден, отправляет еще 401, если нет.
  • сделайте последующий запрос на защищенный URL
  • сервер снова запрашивает авторизацию........

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

Я уверен, что это неправильное поведение.

Если мы посмотрим на то, как ведет себя браузер в этой ситуации:

  • Браузер запрашивает данные с защищенного URL
  • сервер отправляет 401
  • браузер запрашивает у пользователя учетные данные, сохраняет их, передает на сервер
  • сервер проверяет учетные данные, возвращая данные, если они подтверждены, отправляет еще 401, если нет.
  • последующие запросы, сделанные к защищенным URL-адресам, не запрашивают учетные данные, поскольку сеансом управляет браузер.

Я создаю NSURLCredential и сохраняю его в NSURLCrendtialStorage .Затем, когда приложение получает 'didReceiveAuthenticationChallenge', я извлекаю учетные данные из хранилища и передаю их обратно, создавая учетные данные, если они не существуют (по первому запросу).

Мы были бы очень признательны за любую помощь.Спасибо.

Это было полезно?

Решение

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

Действительно, одна из главных причин использования Digest заключается в том, чтобы не использовать сеансы только для поддержания состояния входа в систему.Сеансы являются тяжелыми и снижают масштабируемость.

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

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

Если у вас один и тот же одноразовый номер, используемый в каждом запросе, то пользовательский агент продолжит использовать его вместе с "ha1" от пользователя / pass для запроса последующих ресурсов.Это делается заблаговременно, поэтому вызов никогда не возникает.

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

Следовательно, если вы получаете запрос от пользовательского агента с недопустимым заголовком авторизации, но причина, по которой он недействителен, заключается в том, что одноразовый номер неверен (используется номер с истекшим сроком действия), тогда в вашем запросе укажите "устаревший= true" (по умолчанию значение false).Это информирует агента пользователя о том, что ваша причина отклонения - одноразовый номер устарел (конечно, другая информация также может быть неверной, но это не имеет значения, поскольку вы не собираетесь позволять ей воспроизводиться в любом случае).

При получении такого устаревшего значения = true пользовательский агент будет знать, что он не авторизован, но вместо того, чтобы запрашивать пользователя (или выдавать исключение, если это компонент без пользовательского интерфейса), повторит старые критерии с новым одноразовым номером.

Я не могу сказать, влияет ли на вас что-то из этого, но то, как определяются и сигнализируются одноразовые номера и несвежесть, - это, безусловно, первое, на что я бы обратил внимание.

Другие советы

Я написал приложение для iPhone с HTTP-аутентификацией и испытал то, что вы описываете.(Мое приложение использует базовую аутентификацию вместо дайджест-аутентификации, но здесь это не имеет большого значения.)

Причина проблемы кроется на стороне iPhone.Сервер должен ответить с помощью 401, если iPhone не отправляет учетные данные в заголовке HTTP-запроса.И на самом деле это не так, хотя это легко могло бы произойти, как только учетные данные будут сохранены в хранилище учетных данных.

Это странное поведение серьезно повлияло на скорость работы приложения, поскольку каждый запрос вызывал два обхода сервера вместо одного (первый со статусом 401, второй со статусом 200).

Я решил это, вручную установив учетные данные в заголовке HTTP-запроса:

NSString* credentials = [NSString stringWithFormat: @"%@:%@", usr, pwd];
const char* credentialsChars = [credentials cStringUsingEncoding: NSUTF8StringEncoding];
credentials = [CommunicationUtil stringBase64WithData: (const UInt8*) credentialsChars length: strlen(credentialsChars)];
NSString* authorizationHeader = [NSString stringWithFormat: @"Basic %@", credentials];

NSMutableURLRequest* request =
    [[NSMutableURLRequest alloc] initWithURL: url 
        cachePolicy: NSURLRequestReloadIgnoringLocalCacheData
        timeoutInterval: 15];

    [request setValue: authorizationHeader forHTTPHeaderField: @"Authorization"];

Теперь мое приложение работает очень плавно и очень отзывчиво.

Решение будет выглядеть немного иначе для дайджест-аутентификации.Но вы поймете идею.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top