Поддержка CORS в службах WCF REST - PullRequest
19 голосов
/ 29 августа 2011

У меня есть служба WCF REST, размещенная в службе Windows, и я хочу отправить HTTP-заголовок Access-Control-Allow-Origin (определенный как часть CORS ) с каждым ответом.

Моя попытка решения заключалась в том, чтобы в реализации IDispatchMessageInspector было что-то вроде следующего:

public void BeforeSendReply(ref Message reply, object correlationState)
{
    var httpResponse = reply.Properties["httpResponse"] as HttpResponseMessageProperty;
    if (httpResponse != null)
    {
        // test of CORS
        httpResponse.Headers["Access-Control-Allow-Origin"] = "*";
    }
}

Обычно это работает, но, к сожалению, моя служба также использует Базовая HTTP-авторизация , что означает, что, когда запрос приходит без заголовка авторизации, WCF автоматически отправляет ответ 401 с запросом учетных данных. К сожалению, WCF не вызывает мой IDispatchMessageInspector во время этого первоначального обмена, поэтому заголовок Access-Control-Allow-Origin не добавляется к первоначальному обмену.

Проблема возникает, когда я пытаюсь вызвать службу из браузера. CORS указывает, что запросы между источниками должны быть разрешены, только если домен источника соответствует домену, указанному в заголовке ответа Access-Control-Allow-Origin (* соответствует всем доменам). К сожалению, когда браузер видит начальный ответ 401 без заголовка Access-Control-Allow-Origin, он запрещает доступ (в соответствии с той же политикой происхождения ).

Есть ли способ добавить заголовок к первоначальному ответу 401, автоматически отправляемому WCF?

Ответы [ 2 ]

23 голосов
/ 14 октября 2011

Этот парень спас мой день.

http://blogs.microsoft.co.il/blogs/idof/archive/2011/07.aspx

Я собираюсь разместить здесь некоторые его заметки, на случай, если однажды веб-страница умрет.(Я терпеть не могу найти ссылки «Ваш ответ - ЗДЕСЬ», а затем ссылка не работает.)

<behaviors> 
  <endpointBehaviors> 
    <behavior name="webSupport"> 
      <webHttp /> 
      <CorsSupport /> 
    </behavior> 
  </endpointBehaviors> 
</behaviors> 
<extensions> 
  <behaviorExtensions> 
    <add name="CorsSupport" type="WebHttpCors.CorsSupportBehaviorElement, WebHttpCors, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
  </behaviorExtensions> 
</extensions> 
<services> 
  <service name="Service.JSonService"> 
    <endpoint address="http://localhost:8080" behaviorConfiguration="webSupport” binding="webHttpBinding" contract="Service.IJSonService" /> 
  </service> 
</services>

Теперь вам нужно найти его загружаемую библиотеку под названием «WebHttpCors.dll».

Но есть достаточно (выше), чтобы помочь вам Google / Bing ваш путь к разрешению.

Часть, которая бросала меня в цикл (в моем сценарии), заключается в том, что IE работал, но Firefoxне работал.

Моя исходная страница была:

http://localhost:53692/test/WCFCallTestViaJQ14.htm

Итак, мой сервис по адресу:

http://localhost:8002/MyWCFService/MyWCFMethodByWebGet?state=NC&city=Raleigh

Итак, у меня был localhost << - >> localhostтрафик.

**** Но порты были разные.(53692 и 8002) ****

IE был в порядке.Firefox не согласился с этим.

Тогда вы должны помнить, что каждый браузер обрабатывает свои запросы .Send () по-своему (то есть внутри JQUERY).

Теперь все это имеет смысл.

//JavaScript snipplet from JQuery library

if (window.XMLHttpRequest) {

    returnObject = new XMLHttpRequest();

} else if (window.ActiveXObject) {

    returnObject = new ActiveXObject("Microsoft.XMLHTTP");

} else {

msg = "Your browser doesn't support AJAX!";

}

Вот некоторые ключевые слова, фразы, которые я гуглил / переигрывал, что, наконец, привело меня куда-то.ЧТО ДЕЛАЕТ КОД:

Например, он говорит:

Заголовок «Access-Control-Allow-Origin» со значением «*»

Это может или не может быть то, что вы хотите.Возможно, вы захотите лучше контролировать это значение (заголовки) и другие (методы и источники).

Среда разработки - это одно.(Используйте все *, которые вы хотите).

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

  allowed-origins: '*'
  allowed-headers: '*'
  allowed-methods: '*'
6 голосов
/ 31 августа 2011

Чтобы достичь того, что вы хотите, вам нужно самостоятельно обработать авторизацию, что возможно путем реализации + регистрации HttpModule ... там вы бы выполнили 401, а вместе с ней и любой http-заголовок, который вы хотите ... есть даже пример реализация здесь на SO - см. Добавление базовой аутентификации HTTP к службе REST WCF

РЕДАКТИРОВАТЬ - после комментария от OP:

Поскольку комментарий ОП говорит о том, что он является хостингом, решение не с HTTPModule, а фактически с IDispatchMessageInspector.BeforeSendReply и с IDispatchMessageInspector.AfterReceiveRequest.

Авторизация должна быть настроена на «Нет» и реализована / обработана пользователем в IDispatchMessageInspector - таким образом, вы можете добавить любой заголовок при выдаче 401. В противном случае, во время выполнения Basic Auth не вызовет ваш IDispatchMessageInspector до правильной / положительной аутентификации.

Хотя это работает, ОСТЕРЕГАЙТЕСЬ, что это означает, что вы сами внедряете код, чувствительный к безопасности, и, следовательно, должны принять соответствующие меры для обеспечения его правильной реализации ...

...