Междоменная поддержка Ajax JSON POST для службы RESTful WCF с использованием безопасности transportCredentialOnly

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

  • Веб-сервер IIS с HTML, JS и т. д. на хосте:iis.mycompany.com(упоминается как foo)
  • Веб-службы WCF RESTful, размещенные через службу Windows на хосте:wcf.mycompany.com(упоминается как бар)

Javascript из foo работает, выполняя ajax-вызовы RESTful(GETили POSTв зависимости от действия )к службам WCF на панели , очевидно, что это междоменные вызовы, поскольку они не находятся на одном хосте.

Javascript использует структуру jQuery (1.7.2 )для управления DOM и выполнения ajax-вызовов к панели , ожидаемый тип содержимого для POSTSJSON, а ответ от GETSдолжно быть JSONслишком (application/json ).

В панели службы WCF настроены с использованием TransportCredentialOnlyв качестве режима безопасности, а тип учетных данных транспортного клиента — NTLM, поэтому только пользователи, прошедшие проверку подлинности, могут обращаться к службам.

Поддержка CORS была добавлена ​​в службы bar WCF с использованием расширения WCF :

http://blogs.msdn.com/b/carlosfigueira/archive/2012/05/15/implementing-cors-support-in-wcf.aspx

. Мы добавили дополнительные заголовки и изменили некоторые из уже содержащихся в публикации материалов на основе многочисленных статей в Интернете :

property.Headers.Add("Access-Control-Allow-Headers", "Accept, Content-Type");
property.Headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
property.Headers.Add("Access-Control-Max-Age", "172800");
property.Headers.Add("Access-Control-Allow-Origin", "http://iis.mycompany.com");
property.Headers.Add("Access-Control-Allow-Credentials", "true");
property.Headers.Add("Content-type", "application/json");

. Сайты, предоставляющие информацию о включении CORS, предлагают установить для заголовка ответа Access-Control-Allow-Originзначение "*", однаков нашем случае это невозможно, так как мы делаем ajax-вызовы jQuery, используя следующую настройку:

$.ajaxSetup({
  cache: "false",
  crossDomain: true,
  xhrFields: {
    withCredentials: true
  }
});

Как оказалось, вы не можете использовать "*"для принятого источника, когда вы используете "withCredentials"в вызове ajax:

https://developer.mozilla.org/en/http_access_control

"Important note: when responding to a credentialed request, server must specify a domain, and cannot use wild carding."

В настоящее время в нашей лаборатории разработки это не имеет значения, поскольку мы можем жестко закодировать запросы к URL-адресу сервера IIS (foo ).

Теперь основная проблема заключается в попытках POSTзапросов(GETработает с приведенной выше конфигурацией ). Когда браузер пытается выполнить процесс POST, он сначала отправляет на сервер заголовок OPTIONS, запрашивая разрешение OPTIONSдля последующей публикации. Здесь мы хотели бы, чтобы заголовки, которые мы настроили в расширении CORS Support WCF, передавались обратно, однако мы не заходим так далеко; прежде чем ответ вернется как «401 Unauthorized» , я полагаю, что это связано с конфигурацией привязки безопасности транспорта, запрашивающей NTLM, но я не уверен.

Кроме того, я не очень разбираюсь в этом, но я не видел много информации о POSTиспользовании типа контента application/jsonв отличие от text/plainпри выполнении междоменных запросов.

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

Заранее большое спасибо всем, кто вносит свой вклад.

питески:)

ОБНОВЛЕНИЕ:

Похоже, что Chrome (20.x.x )не сталкивается с проблемой отсутствия согласования NTLM для получения ответа заголовка OPTIONSс сервера, но Firefox (13.0.1 )делает это.

Мы также заметили, что кто-то уже опубликовал сообщение об ошибке на форуме Firefox, информацию о котором мы добавили в :

http://bugzilla.mozilla.org/show_bug.cgi?id=751552

. Пожалуйста, проголосуйте за исправление этой ошибки на сайте bugzilla!

Используя следующий код,мы можем наблюдать за сетевой трассировкой, чтобы увидеть сбой Firefox и нормальную работу Chrome:

var url = "http://myWebServiceServer/InstantMessagingService/chat/message/send";
var data = '{ "remoteUserUri" : "sip:foo.bar@mydomain.com", "message" : "This is my message" }';            
var request = new XMLHttpRequest();                     
request.open("POST", url, true);
request.withCredentials = true;
request.setRequestHeader("Content-Type", "application/json");                   
request.send(data);                     
console.log(request);

Отдельно стоит отметить, что IE8 не поддерживает XMLHttpRequestдля междоменных вызовов, отдавая предпочтение своему собственному магическому объекту XDomainRequest, поэтому нам нужно проделать некоторую работу по изменению кода на стороне клиента для обработки случаев IE8 и мира.. (Спасибо IE8 ).

/me скрещивает пальцы, чтобы Mozilla исправила ошибку Firefox.

ОБНОВЛЕНИЕ 2:

После некоторых раскопок выяснилось, что IE8 XDomainRequestнельзя использовать для выполнения междоменных запросов, где необходимо согласовать NTLM, это в основном означает, что безопасность нашей привязки WCF не может использоваться из-за ограничений в веб-браузере.

http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx

"No authentication or cookies will be sent with the request"

Итак, я думаю, что мы зашли так далеко, как сейчас. Похоже, нам придется создать нашу собственную аутентификацию по токену и передать ее службе WCF в файле cookie или в случае IE8 POSTэто с JSON. Затем службе WCF придется расшифровывать данные и использовать их вместо ServiceSecurityContext.Current.WindowsIdentity, к которым у нас ранее был доступ с аутентификацией NTLM.

8
задан peteski 5 July 2012 в 16:06
поделиться