Почему, когда я выдаю себя за службу WCF, моя служба не может загружать System.Transactions, когда я пытаюсь выполнить запрос 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)

person Simon    schedule 10.11.2008    source источник


Ответы (7)


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

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

person Kwal    schedule 10.11.2008
comment
У меня есть администратор для включения делегирования, и, похоже, это помогло службе. Однако эта служба вызывает другую внутреннюю службу, и сейчас делегирование оттуда падает. - person Simon; 10.11.2008
comment
У вас проблемы с DTC? Возможно, вам придется изучить возможность его включения, если транзакция переключается на другую машину, минуя службу. Что касается учетных данных, используете ли вы метод Windowsidentity.Impersonate для олицетворения при вызове другой службы? - person Kwal; 03.12.2008

Устанавливает ли ваш клиент 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>

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

person huseyint    schedule 26.11.2008

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

[OperationBehavior(Impersonation:=ImpersonationOption.Required)]

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

person Community    schedule 08.01.2009

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

person Marc Gravell    schedule 10.11.2008

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

person Simon    schedule 11.11.2008

Спасибо, Хусейн. Я борюсь с этим последние полтора дня. Вот кое-что, что сэкономило бы мне массу времени. Надеюсь, это сэкономит время кому-то еще. У меня были проблемы с SQLConnection и олицетворением, когда доступ к реестру запрещен с использованием безопасности транспорта. Я пробовал даже использовать transportwithmessagecredential. Внутри procmon я получал "Bad Impersonation". Моя конфигурация - IIS 7, в виртуальном каталоге включена только проверка подлинности Windows, и я отключил проверку подлинности в режиме ядра. В базовых настройках я установил сквозную аутентификацию.

Конфигурация службы -

  <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>
person Community    schedule 01.07.2009

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

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

person Abdelrahman ELGAMAL    schedule 30.03.2015