Как заставить веб-службу WSE 3.0 олицетворять личность моего клиента?

У меня есть веб-служба на основе WSE 3.0, работающая в Windows Server 2003 под IIS 6.0. Я хочу, чтобы процесс веб-службы выдавал себя за пользователя клиента, который отправляет запрос веб-службы, однако служба не выдает себя за клиента.

Веб-приложение имеет собственный пул приложений, который в настоящее время настроен на запуск под удостоверением сетевой службы. Учетная запись компьютера Windows Server 2003 была включена для делегирования в Active Directory (по крайней мере, по словам моего ИТ-специалиста). Политика службы WSE (в wse3policyCache.config) выглядит так:

<policy name="GeneratedServicesPolicy">
    <kerberosSecurity establishSecurityContext="false" renewExpiredSecurityContext="true" requireSignatureConfirmation="false" messageProtectionOrder="SignBeforeEncrypt" requireDerivedKeys="true" ttlInSeconds="300">
        <protection>
            <request signatureOptions="IncludeAddressing, IncludeTimestamp, IncludeSoapBody" encryptBody="false" />
            <response signatureOptions="IncludeAddressing, IncludeTimestamp, IncludeSoapBody" encryptBody="false" />
            <fault signatureOptions="IncludeAddressing, IncludeTimestamp, IncludeSoapBody" encryptBody="false" />
        </protection>
     </kerberosSecurity>
     <requireActionHeader />
</policy>

Служба имеет следующие записи (среди прочего) в своем файле web.config:

<identity impersonate="false"/>
<authentication mode="Windows"/>

Для приложения включен анонимный доступ (это необходимо, так как безопасность на транспортном уровне не используется службой, а на уровне сообщений). Учетная запись компьютера имеет следующие зарегистрированные SPN:

HOST/RD360-2
HOST/rd360-2.mycompany.com

В wse3policyCache.config клиента есть следующее:

<policy name="KerbClient">
    <kerberosSecurity establishSecurityContext="false" renewExpiredSecurityContext="true" requireSignatureConfirmation="false" messageProtectionOrder="SignBeforeEncrypt" requireDerivedKeys="true" ttlInSeconds="300">
        <token>
            <kerberos targetPrincipal="HOST/rd360-2.mycompany.com" impersonationLevel="Impersonation" />
        </token>
        <protection>
            <request signatureOptions="IncludeAddressing, IncludeTimestamp, IncludeSoapBody" encryptBody="false" />
            <response signatureOptions="IncludeAddressing, IncludeTimestamp, IncludeSoapBody" encryptBody="false" />
            <fault signatureOptions="IncludeAddressing, IncludeTimestamp, IncludeSoapBody" encryptBody="false" />
        </protection>
    </kerberosSecurity>
    <requireActionHeader />
</policy>

Код клиента выглядит так:

static void Main(string[] args)
{
    AddFloatsWSWse client = new AddFloatsWSWse();
    client.SetPolicy("KerbClient");

    double result = client.AddFloats(2.3, 3.2);
    Console.WriteLine("Result was: '" + result + "'");
}

Однако служба не выдает себя за личность моего клиента. Я использую log4net в службе, и когда я прошу распечатать %username в журнале трассировки ASP.NET, это всегда NT AUTHORITY\NETWORK SERVICE, а не идентификатор пользователя клиента. Есть ли что-то, что я делаю неправильно? Есть ли где-нибудь, где я могу посмотреть, пытается ли WSE выполнить олицетворение и терпит неудачу? Я вижу следующие записи в моем журнале событий (MYDOMAIN и MYUSER здесь скрыты):

Event Type: Success Audit
Event Source:   Security
Event Category: Privilege Use 
Event ID:   576
Date:       12/9/2009
Time:       11:07:16 AM
User:       MYDOMAIN\MYUSER
Computer:   RD360-2
Description:
    Special privileges assigned to new logon:
        User Name:  MYUSER
        Domain:     MYDOMAIN
        Logon ID:       (0x0,0x4B410AE)
        Privileges: SeSecurityPrivilege
                SeBackupPrivilege
                SeRestorePrivilege
                SeTakeOwnershipPrivilege
                SeDebugPrivilege
                SeSystemEnvironmentPrivilege
                SeLoadDriverPrivilege
                SeImpersonatePrivilege

----------------------------------------------------------------------------------

Event Type: Success Audit
Event Source:   Security
Event Category: Logon/Logoff 
Event ID:   540
Date:       12/9/2009
Time:       11:07:16 AM
User:       MYDOMAIN\MYUSER
Computer:   RD360-2
Description:
    Successful Network Logon:
        User Name:  MYUSER
        Domain:     MYDOMAIN
        Logon ID:   (0x0,0x4B410AE)
        Logon Type: 3
        Logon Process:  Kerberos
        Authentication Package: Kerberos
        Workstation Name:   
        Logon GUID: {OBFUSCATED}
        Caller User Name:   -
        Caller Domain:  -
        Caller Logon ID:    -
        Caller Process ID: -
        Transited Services: -
        Source Network Address: -
        Source Port:    -

И в моем файле трассировки WSE я вижу:

<processingStep description="Entering SOAP filter Microsoft.Web.Services3.Design.RequireSoapHeaderAssertion+RequireSoapHeaderFilter" />
<processingStep description="Exited SOAP filter Microsoft.Web.Services3.Design.RequireSoapHeaderAssertion+RequireSoapHeaderFilter" />
<processingStep description="Entering SOAP filter Microsoft.Web.Services3.Design.KerberosAssertion+ServiceInputFilter" />
<processingStep description="Exited SOAP filter Microsoft.Web.Services3.Design.KerberosAssertion+ServiceInputFilter" />

так что, по крайней мере, я знаю, что расширения Kerberos обрабатывают мои заголовки Kerberos.

Редактировать: мой веб-сервис затем использует проприетарную клиентскую коммуникационную библиотеку для вызова другого сервера с помощью SSPI/IWA (назовем этот третий сервер сервером foo). Я хочу, чтобы он использовал идентификатор клиента, когда он делает этот второй вызов на сервер foo. Это означает, что эта клиентская коммуникационная библиотека вызывает AcquireCredentialsHandle и InitializeSecurityContext, используя SPN сервера foo и другой службы. В данном конкретном случае сервер foo фактически работает на том же компьютере, что и веб-служба WSE (поэтому он использует имя участника-службы mycompany/rd260-2). Поскольку этот второй прыжок относится к той же машине, я ожидаю, что он будет использовать NTLM, но он все равно должен олицетворять удостоверение пользователя моего клиента веб-службы, не так ли? В журналах сервера foo я вижу, что он принимает соединение, использует предоставленный контекст безопасности IWA и сообщает мне, что на основе этого контекста безопасности подключающимся пользователем является rd36-2$, который является учетной записью компьютера, поскольку веб-служба WSE работает в IIS под идентификатором сетевой службы (который, в свою очередь, связан с учетной записью компьютера). В журналах сервера foo после получения контекста безопасности IWA я в конечном итоге хочу увидеть личность пользователя, отправившего запрос веб-службы. Было бы полезно переместить сервер foo на другую машину, чтобы посмотреть, имеет ли это какое-то отношение к этому?


person Zach    schedule 09.12.2009    source источник


Ответы (2)


Маркер Kerberos, используемый с WSE 3, является механизмом безопасности на уровне сообщений и только аутентифицирует клиента. На самом деле он не меняет контекст безопасности, как в IWA, поэтому вы не заметите ничего другого в журнале трассировки как таковом. Чтобы фактически выдать себя за клиента, вам необходимо:

  • Включите олицетворение токена безопасности с помощью impersonationLevel="Impersonation" в элементе <kerberos> (что вы уже сделали); и
  • Пусть ваш WebMethod создаст WindowsImpersonationContext на основе идентификатора токена.

Пример:

WindowsIdentity identity =
    (WindowsIdentity)RequestSoapContext.Current.IdentityToken.Identity;
WindowsImpersonationContext impersonationContext = null;
try
{
    impersonationContext = identity.Impersonate();

    // Perform your work here
    // ...
}
finally
{
    if (impersonationContext != null)
    {
        impersonationContext.Undo();
    }
}
person Aaronaught    schedule 12.12.2009
comment
Спасибо за ваши предложения! Я добавил еще несколько деталей к моему вопросу, описывающих работу, которую выполняет служба. В моем журнале трассировки я все еще вижу процесс, работающий как NT Authority\Network Service, даже после того, как токен Kerberos обрабатывается инфраструктурой WSE. Но, возможно, исходя из вашего комментария, мне никогда не следует ожидать увидеть личность пользователя в журнале даже после успешного олицетворения? Кажется, я вспомнил, что когда вы выполняете IWA на транспортном уровне через IIS в сочетании с олицетворением, вы видите идентификатор пользователя клиента в журналах трассировки. Отличается ли это только для TLS IWA? - person Zach; 12.12.2009
comment
Насколько я знаю, ИВА здесь не при чем. Клиенты WSE подключаются анонимно и аутентифицируют/шифруют/подписывают на уровне сообщения. Если мне не изменяет память, вы никогда не увидите олицетворяемого пользователя в журнале трассировки. К сведению: WCF делает WA совершенно по-другому, Microsoft изменила его, потому что версия WSE была такой хакерской. - person Aaronaught; 12.12.2009
comment
Кроме того, если проделанная работа включает вызов какой-либо проприетарной библиотеки с поддержкой SSPI, то вполне возможно, что библиотека пытается получить свой контекст откуда-то еще, а не от вызывающей стороны. Как я уже упоминал, сначала попробуйте очень простой тест, т. е. настройте ACL для файла где-нибудь с правами доступа, предоставленными пользователю, которого вы хотите олицетворять, а затем попробуйте получить доступ к файлу в своем методе WebService. - person Aaronaught; 12.12.2009
comment
Я понял! Ключ был в том, чтобы фактически выполнить олицетворение самостоятельно (после получения токена kerberos из текущего контекста мыла). По-видимому, инфраструктура WSE на самом деле не выполняет олицетворение, это должен делать клиентский код. После того, как я добавил код, на который вы ссылаетесь (WindowsIdentity.Impersonate), я вижу свой реальный идентификатор клиента в журнале, и сторонняя коммуникационная библиотека правильно использует этот идентификатор для своего вызова. Аарон, не могли бы вы добавить информацию о том, что структура WSE не выдает себя за другое лицо, тогда я отмечу ваш ответ как принятый. - person Zach; 14.12.2009

Насколько я понимаю, ситуация такова, что когда вы пытаетесь сделать второй прыжок, билет Kerberos сбрасывается. В сценарии с двойным переходом билет Kerberos будет удален на втором переходе.

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

person pipelinecache    schedule 12.12.2009