2012-03-21 2 views
4

Моя установка немного сложна, поэтому позвольте мне сначала разобраться.WCF двойное олицетворение?

У нас есть веб-служба WCF, которая получает данные из разных источников через несколько разных API и возвращает эти данные клиенту. Запрашиваемая защита заключается в том, что это делается по HTTPS (рабочий) Стандарт IIS заключается в том, что для пула приложений следует использовать базовую учетную запись сетевой службы IIS и использовать олицетворение .net.

Моя проблема заключается в том, что веб-служба должна всегда запускаться под идентификатором процесса AD независимо от того, кто ее называет, но также должен проверить, какие группы AD вы используете, чтобы определить, какие функции доступны. Теперь я могу настроить мой web.config для использования и такого рода работ, чтобы он всегда выполнялся как Blah, но затем я не знаю, как заставить его выдавать/проверять вызывающего пользователя, чтобы узнать, какие функции у них есть.

** Изменить: забыл упомянуть, что вызывающий клиент должен иметь возможность передавать UN/PASS вместо своего токена Windows. Служба ФОС должен verfiy сво действующий AD ООН и PASS, а также опрос, какие группы он в

ответ

3

Это звучит, как вы хотите HostingEnvironment.Impersonate

. Пример:

using (var imp = HostingEnvironment.Impersonate()) 
{ 
    // code now executes in the context of the authenticated user, 
    // rather than the service account 
} 

Это работает фантастически, к сожалению, стандарт здесь заключается в том, чтобы не использовать пулы приложений, так как для них легче управлять паролями, если их в каждой команде держать их в курсе, помещая их в web.config

Ну, это кажется контр-интуитивным, но я столкнулся с худшими политиками в свое время, поэтому мне вряд ли судить. ;)

Как я упоминал в своем комментарии, есть перегрузки Impersonate, которые позволят вам олицетворять произвольную учетную запись. Чтобы сделать это, вы должны получить токен идентификации Windows для этого пользователя, и это нетривиально, а не, насколько мне известно, то, что вы можете сделать на 100% в управляемом коде. Вам придется использовать неуправляемый код, и вам нужно будет узнать имя пользователя и пароль выданной вами учетной записи в своем приложении. Это гораздо менее безопасно, чем просто установка учетной записи в качестве идентификатора пула приложений, если вы когда-нибудь захотите аргументировать точку с вашим сетевым архитектором BTW. Просто некоторые боеприпасы для тебя.

Во всяком случае, вот пример код я адаптировано из интернетов:

#region native imports. 
public const int Logon_LogonTypeInteractive = 2; 
public const int Logon_ProviderDefault = 0; 
public const int Duplicate_ImpersonationLevelImpersonate = 2; 

[DllImport("advapi32.dll")] 
public static extern bool LogonUser(string lpszUserName, string lpszDomain, string lpszPassword, 
    int dwLogonType, int dwLogonProvider, ref IntPtr phToken); 
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] 
public static extern bool DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken); 

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] 
public static extern bool RevertToSelf(); 

[DllImport("kernel32.dll", CharSet=CharSet.Auto)] 
public static extern bool CloseHandle(IntPtr handle); 
#endregion native imports. 

#region elsewhere... 
public IntPtr GetWindowsTokenForImpersonation(string username, string password, string domain) 
{ 
    IntPtr loginToken = IntPtr.Zero; 
    IntPtr workingToken = IntPtr.Zero; 
    bool success 
    if(!RevertToSelf()) 
    { 
     return IntPtr.Zero; 
     // failed to eliminate any existing impersonations. This block may not be necessary depending on your code 
    } 
    if(!LogonUserA(username, domain, password, Logon_LogonTypeInteractive, Logon_ProviderDefault, ref loginToken)) 
    { 
     return IntPtr.Zero; 
     // failed to log in the user 
    } 

    if(!DuplicateToken(loginToken, Duplicate_ImpersonationLevelImpersonate, ref workingToken) 
    { 
     if(loginToken != IntPtr.Zero) 
     { 
      CloseHandle(loginToken); 
     } 
     return IntPtr.Zero; 
     // failed to get a working impersonation token 
    } 

    CloseHandle(loginToken); 
    return workingToken; // NOTE: You must dispose this token manually using CloseHandle after impersonation is complete. 
} 
#endregion elsewhere 

#region where you want to impersonate 

var token = GetWindowsTokenForImpersonation(username, password, domain); 
if(token != IntPtr.Zero) 
{ 
    using(var imp = HostingEnvironment.Impersonate(token)) 
    { 
     // code here executes under impersonation 
    } 
    CloseHandle(token); 
} 
#endregion 
+0

Я думаю, что мой пост может быть запутанным. Идентификатор пула приложений - это только базовая учетная запись IIS. Идентификатор процесса Я хочу, чтобы всегда запускать приложение, как «Домен \ Служба_аккаунта1», идентификатор вызывающего абонента - «Домен \ Пользователь». Служба wcf должна олицетворять «Domain \ Serviceaccount1» для запуска любой из функций, но должна проверять «Domain \ User», чтобы гарантировать, что пользователь находится в правильных группах для запуска этих функций. Фактический идентификатор пула приложений не должен использоваться ни для чего. – OPcorki

+0

Почему бы не просто установить Serviceaccount1 как идентификатор пула приложений? Тем не менее, есть перегрузки Impersonate, которые позволяют вам олицетворять конкретную учетную запись. – Randolpho

+0

Это работает фантастически, к сожалению, стандартом здесь является не использование пулов приложений, поскольку управление паролями для них проще, если в каждой команде их обновлять, помещая их в web.config – OPcorki

Смежные вопросы