К сожалению, я определил (проанализировав исходный код ссылки WCF и помощь инструмента Fiddler для прослушивания сеанса HTTP), что это ошибка в стеке WCF.
Используя Fiddler, я заметил, что моя служба WCF вела себя в отличие от любого другого веб-сайта, который использует обычную проверку подлинности.
Чтобы было ясно, это то, что должно произойти:
- браузер посылает запрос
GET
без каких-либо знаний о том, что пароль даже необходимо.
- Веб-сервер отклоняет запрос с состоянием
401 Unauthorized
и включает заголовок WWW-Authenticate
, содержащий информацию о приемлемых методах проверки подлинности.
- Браузер предлагает ввести учетные данные.
- Браузер отправляет
GET
запрос и включает соответствующий заголовок Authentication
с полномочиями.
- Если учетные данные были верны, веб-сервер отвечает
200 OK
и веб-страницей. Если учетные данные были неправильными, веб-сервер отвечает 401 Unauthorized
и включает в себя тот же заголовок WWW-Authenticate
, что и в Шаге 2.
Что на самом деле происходит с моей службы WCF был такой:
- браузер посылает запрос
GET
без каких-либо знаний о том, что пароль даже необходимо.
- WCF отмечает, что заголовок
Authentication
отсутствует в запросе и слепо отклоняет запрос с состоянием 401 Unauthorized
и включает в себя заголовок WWW-Authenticate
. Все нормально до сих пор.
- Браузер запрашивает у пользователя учетные данные. Все еще нормально.
- Браузер отправляет
GET
запрос, включая соответствующий заголовок Authentication
.
- Если учетные данные были верны, веб-сервер отвечает
200 OK
. Все хорошо. Если учетные данные были неверными, WCF отвечает 403 Forbidden
и не содержит никаких дополнительных заголовков, таких как WWW-Authenticate
.
Когда браузер получает статус 403 Forbidden
, он не воспринимает это как неудачную попытку аутентификации. Этот код состояния предназначен для информирования браузера о том, что URL, к которому он пытался получить доступ, не работает. Это никак не связано с аутентификацией. Это страшная сторона влияет на то, что, когда пользователь неправильно вводит свое имя пользователя/пароль (а сервер отклоняется с помощью 403), веб-браузер не перепрофилирует пользователя для повторного ввода своих учетных данных. Фактически веб-браузер считает, что аутентификация прошла успешно, и поэтому сохраняет эти учетные данные для остальной части сеанса!
Имея это в виду, я хотел бы получить разъяснения:
RFC, 2617 (http://www.faqs.org/rfcs/rfc2617.html#ixzz0eboUfnrl) не упоминает где-либо использование кода 403 Forbidden
статуса. В самом деле, что это на самом деле должно сказать по этому вопросу заключается в следующем:
Если исходный сервер не желает принять полномочия, отправленные с запросом, он должен вернуть (Несанкционированный) ответ 401 , Ответ ДОЛЖЕН содержать заголовок WWW-Authenticate , содержащий по меньшей мере одну ошибку (возможно, новую), применимую к запрашиваемому ресурсу.
WCF ни в одном из них. Он не правильно отправляет код состояния 401 Unauthorized
. Он также не включает заголовок WWW-Authenticate
.
Теперь найти дымящийся пистолет в пределах исходного кода WCF:
я обнаружил, что в HttpRequestContext
классе является метод, называемый ProcessAuthentication
, который содержит следующее (выдержка):
if (!authenticationSucceeded)
{
SendResponseAndClose(HttpStatusCode.Forbidden);
}
Я защищаю Microsoft много чего, но это невозможно.
К счастью, у меня это работает на «приемлемом» уровне. Это просто означает, что если пользователь случайно ошибочно вводит свое имя пользователя/пароль, единственный способ получить еще одну попытку - полностью закрыть свой веб-браузер и перезапустить его, чтобы повторить попытку.Все потому, что WCF не отвечает на неудачную попытку аутентификации с 401 Unauthorized
и WWW-Authenticate
заголовком согласно спецификации.
Время переключиться на реальную инфраструктуру http, например openrasta :) – SerialSeb
@serialseb У меня не было сердца, чтобы сказать ему, что я отказался от попыток решить проблемы с auth на WCF и сразу направился прямо к HttpListener. –
Привет, ребята :) Даррел, я видел ваши комментарии в другом обсуждении и считаю, что я рассматривал это как вариант. К счастью, мы еще не инвестировали слишком много в WCF REST. Таким образом, мы можем пойти вперед и остановить его. – nbevans