WCF jsonP с аутентификацией Windows - возможно? - PullRequest
4 голосов
/ 26 октября 2011

Я размещаю сервис wcf, который выводит jsonp. Ответ от IIS (с включенной аутентификацией Windows):

Междоменный обратный вызов JavaScript не поддерживается в аутентифицированных сервисах.

Есть ли способ обойти это? У меня должна быть включена аутентификация Windows, но я также хотел бы использовать wcf для сервера jsonp

Моя веб-конфигурация выглядит следующим образом

<system.serviceModel>
  <behaviors>
    <endpointBehaviors>
      <behavior name="webHttpBehavior">
        <webHttp />
      </behavior>
    </endpointBehaviors>
  </behaviors>
  <bindings>
    <webHttpBinding>
      <binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true" >
        <security mode="TransportCredentialOnly">
          <transport clientCredentialType="Ntlm"/>
        </security>
      </binding>
    </webHttpBinding>
  </bindings>
  <services>
    <service name="ServiceSite.CustomersService">
      <endpoint address="" binding="webHttpBinding"
                bindingConfiguration="webHttpBindingWithJsonP" contract="ServiceSite.CustomersService"
                behaviorConfiguration="webHttpBehavior"/>
    </service>
  </services>
</system.serviceModel>

1 Ответ

5 голосов
/ 22 декабря 2011

Немного поздно, я вижу, но поскольку ответов нет, и я столкнулся с похожей проблемой:

Единственный способ, которым я смог использовать службу WCF с проверкой подлинности Windows (размещенную в IIs 7.5)к нему обращались из междоменного клиента, чтобы клиенты звонили через прокси.В прокси есть дополнительный переход, но теперь я больше не полагаюсь на JSONP.Служба настроена с двумя конечными точками, soap и json - я вставил всю модель службы внизу для справки.

Итак, клиентские приложения (все они являются веб-приложениями .NET):

A) Создайте метод $ .ajax POST для страницы (или метод контроллера [HttpPost] MVC), который вызывает WCF как мыльную веб-ссылку:

function EmployeeSearch() {
    var searchname = $("#userSearchText").val();
    if (searchname.length > 0) {
        var d = { name: searchname, pageSize: _pageSize, page: _currentPage };
        var jsonData = JSON.stringify(d);
        if (json.length > 0) {
            $.ajax({
                type: "POST",
                url: "Home/EmployeeSearch",
                data: jsonData,
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: employeeSearchSuccess,
                error: onError
            });
        }
    }
}

И метод контроллера (или метод страницы):

    [HttpPost]
    public ActionResult EmployeeSearch(string name, int pageSize, int page)
    {
        var client = new EmployeeServiceClient();
        var searchResult = client.EmployeeSearch(name);
        var count = searchResult.Count();
        var employees = searchResult.Skip((page - 1) * pageSize).Take(pageSize).ToList();

        var viewModel = new EmployeeSearchViewModel
                            {
                                Employees = employees,
                                Size = count
                            };

        return Json(viewModel);
    }

ИЛИ

B) Создайте $ .getJSON для HttpHandler, как описано в Dave Wards http://encosia.com/use-asp-nets-httphandler-to-bridge-the-cross-domain-gap/

В приведенном выше примере WebClient.DownoadString () в методе обработчика ProcessRequest будет принимать следующую строку URL:

http://server/EmployeeService/EmployeeService.svc/Json/EmployeeSearch/searchstring

Оба подхода позволяют моему сервису оставаться под Windows auth, и у клиентов есть несколько способов доступасервис.Дополнительный прыжок раздражает, но я стараюсь не думать об этом.

И вот вам вся справочная модель WCF service для справки:

<behaviors>
    <serviceBehaviors>
        <behavior name="EmployeeServiceBehavior">
            <serviceTimeouts transactionTimeout="01:00:00"/>
            <serviceMetadata httpGetEnabled="true"/>
            <serviceDebug includeExceptionDetailInFaults="true"/>
            <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
        </behavior>
    </serviceBehaviors>

    <!-- we'd use this one if we wanted to ignore the 'd' wrapper around the json result ... we don't -->
    <endpointBehaviors>
        <!-- plain old XML -->
        <behavior name="poxBehavior">
            <webHttp helpEnabled="true" />
        </behavior>
        <!-- JSON -->
        <behavior name="jsonBehavior">
            <enableWebScript />
        </behavior>
    </endpointBehaviors>

</behaviors>

<bindings>
    <basicHttpBinding>
        <binding name="basicBinding"
                hostNameComparisonMode="StrongWildcard"
                receiveTimeout="00:10:00"
                sendTimeout="00:10:00"
                openTimeout="00:10:00"
                closeTimeout="00:10:00"
                maxReceivedMessageSize="2147483647"
                maxBufferSize="2147483647"
                maxBufferPoolSize="524288"
                transferMode="Buffered"
                messageEncoding="Text"
                textEncoding="utf-8"
                bypassProxyOnLocal="false"
                useDefaultWebProxy="true" >
            <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
            <!-- use the following for windows authentication -->
            <security mode="TransportCredentialOnly">
                <transport clientCredentialType="Windows" />
            </security>
        </binding>
    </basicHttpBinding>

    <webHttpBinding>
        <binding name="webBinding"
                receiveTimeout="00:10:00"
                sendTimeout="00:10:00"
                openTimeout="00:10:00"
                closeTimeout="00:10:00"
                maxReceivedMessageSize="2147483647"
                maxBufferSize="2147483647"
                maxBufferPoolSize="524288"
                bypassProxyOnLocal="false"
                useDefaultWebProxy="true"
                >
            <!--crossDomainScriptAccessEnabled="true"-->
            <!-- use the following for windows authentication -->
            <security mode="TransportCredentialOnly">
                <transport clientCredentialType="Windows" />
            </security>
        </binding>
    </webHttpBinding>

</bindings>

<services>
    <service name="EmployeeService.Wcf.EmployeeService" behaviorConfiguration="EmployeeServiceBehavior">
        <endpoint address="Soap" binding="basicHttpBinding" bindingConfiguration="basicBinding" contract="EmployeeService.Wcf.IEmployeeService"/>
        <endpoint address="Json" binding="webHttpBinding" bindingConfiguration="webBinding" behaviorConfiguration="poxBehavior" contract="EmployeeService.Wcf.IEmployeeService" />
    </service>
</services>

<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true"/>

Одно добавление - OperationContract для приведенного выше примера метода:настроить в ServiceContract следующим образом:

    [OperationContract]
    [WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "EmployeeSearch/{name}")]
    List<Employee> EmployeeSearch(string name);
...