Как я могу разрешить веб-службе WCF, которая использует олицетворение для записи в журнал событий Windows?

Я пишу небольшую службу WCF, и я хотел бы иметь возможность писать в настраиваемый журнал событий. Я создал журнал событий и источник, а также минимальную службу, которая может записывать в журнал. Затем я добавил олицетворение и начал получать на клиенте ошибки «Доступ запрещен». При входе на сервер это принимает форму ошибки «Запрошенный доступ к реестру запрещен».

Хотя это не относится к пользователям службы, олицетворяемая учетная запись (обязательно) является членом администраторов (чтобы иметь возможность отлаживать с помощью IIS).

Я получаю те же результаты при запуске тестового клиента WCF на одном компьютере с пользователем без прав администратора и на другом компьютере с пользователем без прав администратора.

Чтобы воссоздать:

  1. Запустите PowerShell от имени администратора
  2. New-EventLog -LogName Test42 -Source Test42.Web
  3. Закройте PowerShell
  4. Запустите Visual Studio от имени администратора
  5. Новый проект - .NET Framework 4.5> Visual C #> WCF> Приложение службы WCF 'ImpSvc1' (* Создать каталог для решения)
  6. Замените содержимое IService1.cs, Service1.svc и Web.config приведенным ниже содержимым.
  7. В окне «Свойства проекта WCF»> «Интернет» (вкладка)> «Серверы» выберите «Локальный IIS» и нажмите «Создать виртуальный каталог».
  8. Постройте проект.
  9. Запустите диспетчер IIS - выберите веб-сайт по умолчанию
  10. Откройте IIS
  11. Вам понадобится пул приложений с учетной записью домена (без специальных разрешений на машине IIS) и интегрированный режим конвейера, поэтому создайте его, если у вас его нет.
  12. Выберите Веб-сайт по умолчанию> Аутентификация. Убедитесь, что проверка подлинности Windows включена, а все остальные отключены.
  13. Выберите ImpSvc1> Основные настройки. Выберите пул приложений сверху.
  14. Закройте диспетчер IIS.
  15. Запустите тестовый клиент WCF. Файл> Добавить службу> http://localhost/ImpSvc1/Service1.svc
  16. Дважды щелкните метод GetDate () и нажмите «Вызов». Вы должны получить ОТВЕТ: user =; dateTime = и событие en, ​​созданное в журнале событий Test42.
  17. Раскомментируйте оператор using, постройте и повторите Invoke, и вы должны получить: RESPONSE: user =; dateTime = и событие en, ​​созданное в журнале событий Test42.
  18. Раскомментируйте оператор EventLog.WriteEntry, постройте и повторите Invoke, и вы должны получить ошибку «Доступ запрещен» в тестовом клиенте WCF.
  19. Если вы запустите проект с отладки, вы увидите, что «Запрошенный доступ к реестру не разрешен».

IService1.cs

using System;
using System.ServiceModel;

namespace ImpSvc1
{
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        String GetData();
    }
}

Service1.svc

using System;
using System.Diagnostics;
using System.Security.Principal;
using System.ServiceModel;

namespace ImpSvc1
{
    public class Service1 : IService1
    {
        public String GetData()
        {
            EventLog.WriteEntry("Test42.Web", "Test message", 
                EventLogEntryType.Information, 1, 0);
            //using (ServiceSecurityContext.Current.WindowsIdentity.Impersonate())
            //{
                //EventLog.WriteEntry("Test42.Web", "Test message from using statement", 
                //    EventLogEntryType.Information, 2, 0);
                return String.Format("RESPONSE: user={0}; dateTime={1}", 
                    WindowsIdentity.GetCurrent().Name, DateTime.Now);
            //}
        }
    }
}

Web.config

<?xml version="1.0"?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" 
         value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" 
                 targetFramework="4.5" />
    <httpRuntime targetFramework="4.5"/>
  </system.web>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding closeTimeout="00:05:00"
                 openTimeout="00:05:00"
                 receiveTimeout="00:10:00"
                 sendTimeout="00:10:00">
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Windows" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" 
                           httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
      <add binding="basicHttpBinding" 
           scheme="http" />
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" 
                               multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="true"/>
    <security>
      <authentication>
        <anonymousAuthentication enabled="false" />
        <windowsAuthentication enabled="true" />
      </authentication>
    </security>
  </system.webServer>

</configuration>

person user2871239    schedule 25.09.2018    source источник
comment
Это, очевидно, проблема с разрешениями, проверьте это, если вы еще не support.microsoft.com/en-au/help/329291/   -  person TheGeneral    schedule 25.09.2018
comment
Также это stackoverflow.com/questions/292883/ и это social.msdn.microsoft.com/Forums/en-US/   -  person TheGeneral    schedule 25.09.2018
comment
Это не совсем та же проблема. Похоже, что все они пытаются создать источник событий из приложения. Я знал, что вам нужны права администратора для создания источника событий, поэтому я создал его отдельно. Мой код успешно записывается в источник перед олицетворением пользователя, но не во время олицетворения. Но похоже, что метод WriteEntry внутри олицетворения не видит источник и поэтому проверяет его перед автоматическим созданием.   -  person user2871239    schedule 25.09.2018
comment
Для создания источников событий требуются права администратора, но любой аутентифицированный пользователь может писать в журнал. Вам необходимо создать источник вне вашего приложения. В этой статье рассказывается, как обойти эти проблемы. stackoverflow.com/a/14252008/3516555   -  person fourwhey    schedule 25.09.2018
comment
@fourwhey - как указано в вопросе, я уже создал источник события и написал в него. Проблема только в том, что я не могу писать в него, выдавая себя за пользователя.   -  person user2871239    schedule 25.09.2018
comment
Только источник события безопасности имеет авторизацию, связанную с записью в него. Все остальные, с оговоркой, что они должны существовать, могут быть записаны любым пользователем. При этом учетная запись, от имени которой выполняется сервисный процесс, должна работать. Я попытаюсь проверить то, что вы видите.   -  person fourwhey    schedule 25.09.2018