У меня есть приложение, которое связывается с сервером, который использует Дайджест-аутентификацию HTTP.
Мне кажется, что управление 'сессией' в iPhone является довольно "черным квадратом" нам разработчики. Действительно ли это верно, что мы не видим, как дескрипторы платформы / сохраняют сеансы HTTP?
Если бы я просто тускл здесь, кто-то хотел бы объяснить, как, вероятно, обработать Дайджест-аутентификацию HTTP на iPhone?
Мои основные пробегают:
Это работает на единственные запросы, но если я выполняю дополнительные, последующие запросы, авторизация запросов к серверу снова. Сервер сохранил сессию для конкретного пользователя, но iPhone не выполняет запрос в рамках той же сессии по некоторым причинам... Поэтому сервер должен вывести объект аутентификации и создать новый каждый раз, когда клиент выполняет запрос к защищенному URL.
Я уверен, что это не корректное поведение.
Если мы смотрим на то, как браузер ведет себя в этой ситуации:
Я создаю NSURLCredential и сохраняю его в NSURLCrendtialStorage. Затем, когда приложение получает 'didReceiveAuthenticationChallenge', я получаю учетные данные от устройства хранения данных и пасую назад его, создавая учетные данные, если это не существует (по первому запросу).
Любая справка значительно ценилась бы.Спасибо.
Во-первых, следует забыть о сеансах HTTP, поскольку они не взаимодействуют с активными входами в систему с дайджест-аутентификацией (есть своего рода возможность получения информации о сеансе, но она другая).
Действительно, одна из основных причин использования Digest - не использовать сеансы только для поддержания состояния входа в систему. Сеансы тяжелые и ухудшают масштабируемость.
Я не могу точно сказать, в чем заключается ваша проблема, но я знаю, что нужно проверить в первую очередь, а именно: правильное использование устаревших и правильное создание одноразовых номеров.
Пользовательские агенты могут обрабатывать аутентификацию без запроса пользователя только в том случае, если их просят обработать один и тот же одноразовый номер, или в другом случае, к которому я вернусь позже (проще объяснить это в таком порядке).
Если в каждом запросе используется один и тот же одноразовый номер, то пользовательский агент продолжит использовать его вместе с «ha1» от пользователя / прохода для запроса последующих ресурсов. Это делается заранее, поэтому проблемы никогда не возникает.
Конечно, использование одного и того же одноразового номера вносит элемент небезопасности, поскольку атаки с повторением становятся тривиальными для любого, кто может перехватить трафик. Nonce придется менять на регулярной основе.
Следовательно, если вы получили запрос от пользовательского агента с недопустимым заголовком авторизации, но он недействителен, потому что одноразовый номер неверен (он использует просроченный), тогда в вашем запросе укажите "stale = true" (по умолчанию false).Это информирует пользовательский агент о том, что ваша причина отклонения заключается в том, что одноразовый номер устарел (конечно, другая информация также может быть неверной, но это не имеет значения, поскольку вы не собираетесь позволять ей играть в любом случае).
При получении такого stale = 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"];
Теперь мое приложение работает очень плавно и быстро реагирует.
Решение для дайджест-аутентификации будет выглядеть несколько иначе. Но вы поняли идею.