Я создал саморазмещенный сервис REST WCF (с некоторым extra's от Предварительного просмотра Стартового набора REST WCF 2). Это все хорошо работает.
Я теперь пытаюсь добавить Стандартную аутентификацию к сервису. Но я поражаю некоторые довольно большие контрольно-пропускные пункты в стеке WCF, который препятствует тому, чтобы я делал это.
Кажется что HttpListener
(который саморазместил сервисное использование WCF внутренне на низком уровне в стеке WCF), блокирует мои попытки вставить a WWW-Authenticate
заголовок на самосгенерированном 401 Unauthorized
ответ. Почему?
Я могу получить работу аутентификации, если я забываю об этом WWW-Authenticate
заголовок (то, которое это кажется Microsoft, сделало также). Но это - проблема. Если я не передаю a обратно WWW-Authenticate
заголовок тогда веб-браузер не отобразит свое стандартное диалоговое окно "входа в систему". Пользователь просто столкнется с a 401 Unauthorized
ошибочная страница без способа на самом деле войти в систему.
Сервисы REST должны быть доступны и для компьютеров и для людей (хорошо, по крайней мере, на ПОЛУЧИТЬ уровне запроса). Поэтому я чувствую, что REST WCF не выполняет фундаментальную часть REST здесь. Кто-либо соглашается со мной?
Кто-либо получил Стандартную аутентификацию, работающую с саморазмещенным сервисом REST WCF? Если так, как Вы делали это?
PS: Очевидно, мои намерения использовать небезопасную Стандартную аутентификацию находятся по предпосылке, что я также получил бы HTTPS/SSL, работающий на мой сервис также. Но это - другой вопрос.
PPS: я попробовал REST WCF Contrib (http://wcfrestcontrib.codeplex.com/), и это имеет точно ту же проблему. Кажется, что эта библиотека не была протестирована в саморазмещенных сценариях.
Спасибо.
К сожалению, я определил (анализируя исходный код ссылки WCF и помощь инструмента Fiddler для сниффинга сеанса HTTP), что это ошибка в WCF куча.
Используя Fiddler, я заметил, что моя служба WCF ведет себя не так, как любой другой веб-сайт, использующий обычную проверку подлинности.
Для ясности, вот что ДОЛЖНО произойти:
GET
, не зная, что пароль вообще нужен. 401 Unauthorized
и включает заголовок WWW-Authenticate
, содержащий информацию о допустимых методах аутентификации. GET
и включает соответствующий заголовок Authentication
с учетными данными. 200 OK
и веб-страницей.
Если учетные данные были неправильными, веб-сервер отвечает сообщением 401 Неавторизовано
и включает тот же заголовок WWW-Authenticate
, что и на шаге 2. С моей службой WCF ДЕЙСТВИТЕЛЬНО происходило следующее:
GET
, не зная, что пароль вообще нужен. Authentication
, и слепо отклоняет запрос со статусом 401 Unauthorized
и включает заголовок WWW-Authenticate
. Пока все нормально. GET
, включая соответствующий заголовок Authentication
. 200 OK
. Все в порядке.
Однако, если учетные данные были неправильными, WCF отвечает сообщением 403 Forbidden
и не включает никаких дополнительных заголовков, таких как WWW-Authenticate
. Когда браузер получает статус 403 Запрещено
, он не воспринимает это как неудачную попытку аутентификации. Этот код состояния предназначен для информирования браузера о том, что URL-адрес, к которому он пытался получить доступ, запрещен. Это никак не связано с аутентификацией. Это имеет ужасный побочный эффект, заключающийся в том, что когда пользователь вводит свое имя пользователя / пароль неправильно (и сервер отклоняет его с 403), тогда веб-браузер не предлагает пользователю повторно ввести свои учетные данные.Фактически, веб-браузер считает, что аутентификация прошла успешно, и поэтому сохраняет эти учетные данные до конца сеанса!
Имея это в виду, я попросил разъяснений:
В RFC 2617 ( http://www.faqs.org/rfcs/rfc2617.html#ixzz0eboUfnrl ) нигде не упоминается использование код состояния 403 Запрещено
. Фактически, он должен сказать по этому поводу следующее:
Если исходный сервер не желает принимать учетные данные, отправленные с запросом , он ДОЛЖЕН вернуть 401 (Несанкционированный) ответ. Ответ ДОЛЖЕН включать поле заголовка WWW-Authenticate , содержащее по крайней мере одну (возможно новую) проблему, применимую к запрошенному ресурсу.
WCF не делает ни того, ни другого. Он также не отправляет правильно код состояния 401 Неавторизованный
. Он также не включает заголовок WWW-Authenticate
.
Теперь, чтобы найти дымящийся пистолет в исходном коде WCF:
Я обнаружил, что в классе HttpRequestContext
есть метод под названием ProcessAuthentication
, который содержит следующее (отрывок) :
if (!authenticationSucceeded)
{
SendResponseAndClose(HttpStatusCode.Forbidden);
}
Я защищаю Microsoft по многим вещам, но это безосновательно.
К счастью, у меня это работает до "приемлемого" уровня. Это просто означает, что если пользователь случайно вводит свое имя пользователя / пароль неправильно, то единственный способ получить еще одну попытку - полностью закрыть свой веб-браузер и перезапустить его, чтобы повторить попытку.Все потому, что WCF не отвечает на неудачную попытку аутентификации заголовком 401 Unauthorized
и WWW-Authenticate
в соответствии со спецификацией.