Получение DefaultNetworkCredentials для передачи в службу WCF

У меня есть служба WCF, которую я создал в WebApplication со следующей конфигурацией в web.config

<service name="RedwebServerManager.WebApplication.DesktopService"
           behaviorConfiguration="ServBehave">
    <endpoint
       address=""
        binding="basicHttpBinding"
        bindingConfiguration="basicBind"
        contract="RedwebServerManager.WebApplication.IDesktopService"/>
  </service>
</services>
<bindings>
  <basicHttpBinding>
    <binding name="basicBind">
      <security mode="TransportWithMessageCredential">
        <transport clientCredentialType="Windows"/>
      </security>
    </binding>
  </basicHttpBinding>
</bindings>

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

    [ServiceContract]
public interface IDesktopService
{
    /// <summary>
    /// Gets the clients.
    /// </summary>
    /// <returns>IEnumerable&lt;ClientServiceModel&gt;.</returns>
    [OperationContract]
    IEnumerable<ClientServiceModel> GetClients();
}

У меня есть приложение Windows Forms, которое использует службу WCF, и я хочу передать учетные данные текущего пользователя с помощью приложения, поскольку все это будет сидеть в нашем домене. Файл app.config выглядит следующим образом

    <system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_IDesktopService">
              <security mode="TransportWithMessageCredential">
                <transport clientCredentialType="Windows" proxyCredentialType="Windows"/>
              </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="https://redwebservermanager.redweb.network/DesktopService.svc"
            binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IDesktopService"
            contract="ManagerService.IDesktopService" name="BasicHttpBinding_IDesktopService" />
    </client>
</system.serviceModel>

Если я вручную установил имя и пароль учетных данных, все работает правильно, но я пытался

managerService.ClientCredentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials

чтобы я мог передавать текущие учетные данные пользователей, но я продолжаю получать ошибку при вызове GetClients(), что имя пользователя и пароль не установлены.

Может ли кто-нибудь мне помочь? Я также попытался добавить

[OperationBehavior(Impersonation = ImpersonationOption.Required)]

но это не имело значения.

Ответы

Ответ 1

Вы можете получить имя пользователя (и другую информацию, отличную от пароля), используя один из следующих способов:

//1. 
System.Security.Principal.WindowsIdentity.GetCurrent();
//2.    
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
    WindowsPrincipal user = (WindowsPrincipal)System.Threading.Thread.CurrentPrincipal;
//3.    
WindowsIdentity ident = WindowsIdentity.GetCurrent();
    WindowsPrincipal user = new WindowsPrincipal(ident);

Но вы не можете получить доступ к паролю пользователя. Пожалуйста, обратитесь к question

После получения информации Identity вы можете передать имя пользователя в WCF с помощью OutgoingMessageHeaders, например:

MessageHeader<string> header = new MessageHeader<string>(userName);
        OperationContextScope contextScope =   new OperationContextScope(InnerChannel);
        OperationContext.Current.OutgoingMessageHeaders.Add(
        header.GetUntypedHeader("String", "System"));

И в реализации сервиса WCF вы можете прочитать его как:

OperationContext context = OperationContext.Current;

            if (context != null)
            {
                try
                {
                    _LoginName = OperationContext.Current.IncomingMessageHeaders.GetHeader<string>("String", "System");          
                }
                catch
                {
                    _LoginName = string.Empty;
                }
            }

Пожалуйста, дайте мне знать, если это поможет или у вас возникнут другие вопросы.

Спасибо, Сома.