Почему, когда я олицетворяю себя в службе WCF, моя служба не может загрузить систему.Транзакции, когда я пытаюсь запустить запрос LINQ to SQL?

у меня есть служба WCF, размещенная в IIS 7.0, которая должна запускать запросы к базе данных. Чтобы получить правильные разрешения для этого, я олицетворяю себя в службе следующим образом:

код

[OperationBehavior(Impersonation = ImpersonationOption.Allowed)]
public void MyOperation(int arg)

конфигурация

<behavior name="ReceivingServiceBehavior">
    <!-- Other behaviors -->
    <serviceAuthorization impersonateCallerForAllOperations="true" />
</behavior>

когда я пытаюсь подключиться и выполнить запрос, я получаю следующее:

Exception - System.IO.FileLoadException: Could not load file or
assembly 'System.Transactions, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089' or one of its dependencies. Either a
required impersonation level was not provided, or the provided
impersonation level is invalid. (Exception from HRESULT: 0x80070542)

File name: 'System.Transactions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' ---> System.Runtime.InteropServices.COMException (0x80070542): Either a required impersonation level was not provided, or the provided impersonation level is invalid. (Exception from HRESULT: 0x80070542)
   at System.Data.Linq.SqlClient.SqlConnectionManager.UseConnection(IConnectionUser user)
   at System.Data.Linq.SqlClient.SqlProvider.get_IsSqlCe()
   at System.Data.Linq.SqlClient.SqlProvider.InitializeProviderMode()
   at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)
   at System.Data.Linq.DataQuery`1.System.Collections.Generic.IEnumerable.GetEnumerator()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Fourth.GHS.MessageRelay.RegistrationDBStorage.FindRegistration(SystemKey key)

7 ответов


Если вы хотите, чтобы SQL-запросы выполнялись как олицетворенное удостоверение, вам может потребоваться включить делегирование на ваш SQL server. Ознакомьтесь с этой статьей для получения дополнительной информации:

http://msdn.microsoft.com/en-us/library/ms730088.aspx


устанавливает ли ваш клиент WCF необходимый "разрешенный уровень олицетворения":

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>

        <!-- .... -->

        <behaviors>
           <endpointBehaviors>
              <behavior name="ImpersonationBehavior">
                 <clientCredentials>
                      <windows allowedImpersonationLevel="Impersonation" />
                 </clientCredentials>
              </behavior>
           </endpointBehaviors>
        </behaviors>
    </system.serviceModel>
</configuration>

по умолчанию установлено значение идентификация если ничего не указано явно. Проверьте этот блог для получения дополнительной информации.


спасибо ребята, Я решил это, прочитав XML под объявлением:

[OperationBehavior(Impersonation:=ImpersonationOption.Required)]

он работал только тогда, когда я читал XML непосредственно из класса WCFService.


Хммм... Я не знаю. Тем не менее, вы можете заставить dll загружаться на ранней стадии. Поскольку вы используете IIS, это, по-видимому,будет в вашем глобальном.asax-что-то вроде создания и выбрасывания TransactionScope должно выполнять эту работу...


поиграв с этим еще немного, самым простым решением для служб IIS hosted services является запуск пула приложений с идентификатором пользователя домена, имеющего необходимые разрешения. Есть, наверное, проблемы с этим с точки зрения безопасности, но для наших целей этого достаточно. Мы можем ограничить разрешения, предоставленные этому пользователю, но все работает без необходимости входить в Kerberos, олицетворение, делегирование и тайны AD.


спасибо huseyint. Я боролся с этим последние полтора дня. Вот кое-что, что сэкономило бы мне кучу времени. Надеюсь, это сэкономит кому-то время. У меня возникли проблемы с SQLConnection и олицетворением, бросающим доступ к реестру, запрещен с помощью транспортной безопасности. Я попытался даже использовать transportwithmessagecredential. Внутри procmon я получал "плохое олицетворение". Мой конфиг IIS 7, virtual dir включена только проверка подлинности windows и я отключил аутентификацию в режиме ядра. Основные настройки я установил его для использования pass through authentication.

Сервис Конфиг -

  <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="false" />
    <services>
      <service behaviorConfiguration="SymitarService.ScheduleServiceBehavior" name="SymitarService.ScheduleService">
        <endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsSecure" contract="SymitarService.IScheduleService">
          <identity>
            <dns value="localhost" />            
          </identity>
        </endpoint>
        <endpoint address="mex" binding="wsHttpBinding" bindingConfiguration="wsSecure" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="SymitarService.UserDirectoryBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceAuthorization impersonateCallerForAllOperations="true" />
        </behavior>
        <behavior name="SymitarService.ScheduleServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceAuthorization impersonateCallerForAllOperations="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <netTcpBinding>
        <binding name="tcpSecure" portSharingEnabled="true" />
      </netTcpBinding>
      <wsHttpBinding>
        <binding name="wsSecure" allowCookies="true">
          <security mode="Transport">
            <transport clientCredentialType="Windows" proxyCredentialType="Windows" />
            <message clientCredentialType="Windows" negotiateServiceCredential="true" />
          </security>
        </binding>
      </wsHttpBinding>
      <mexTcpBinding>
        <binding name="mexSecure" />
      </mexTcpBinding>
    </bindings>
  </system.serviceModel>

и клиент

<system.serviceModel>
    <bindings>
        <wsHttpBinding>
            <binding name="WSHttpBinding_IScheduleService" closeTimeout="01:00:00" openTimeout="01:00:00" receiveTimeout="01:00:00" sendTimeout="01:00:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" useDefaultWebProxy="true" allowCookies="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <reliableSession ordered="true" inactivityTimeout="00:20:00" enabled="false" />
          <security mode="Transport">
            <transport clientCredentialType="Windows" proxyCredentialType="Windows" realm="" />
            <message clientCredentialType="Windows" negotiateServiceCredential="true" establishSecurityContext="true" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name="ImpersonationBehavior">
          <clientCredentials>
            <windows allowedImpersonationLevel="Impersonation" allowNtlm="true"/>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <client>
      <endpoint address="https://server:444/SymitarService/ScheduleService.svc" 
                binding="wsHttpBinding" 
                bindingConfiguration="WSHttpBinding_IScheduleService" 
                contract="Symitar.ScheduleService.IScheduleService" 
                name="WSHttpBinding_IScheduleService"
                behaviorConfiguration="ImpersonationBehavior"
                >
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>

Это решило мою проблему.

щелкните правой кнопкой мыши на Visual studio (какую бы версию вы ни использовали) Свойства Выберите вкладку Совместимость Установите флажок " запустить программу от имени администратора" Откройте проект из расположения файла Запустите приложение