简体   繁体   English

使用WSDualHttpBinding在WCF服务之间共享Windows身份

[英]Share windows identity between WCF services with WSDualHttpBinding

I have two WCF services hosted separately in IIS 7. The first service is callable from outside and uses a WebHttpBinding with windows authentication. 我在IIS 7中分别托管了两个WCF服务。第一个服务可从外部调用,并使用带有Windows身份验证的WebHttpBinding The second service is only called by the first one, using a WsDualHttpBinding . 第二个服务仅由第一个使用WsDualHttpBinding

When the first service is called, I can get the user's windows name from ServiceSecurityContext.Current.WindowsIdentity.Name . 调用第一个服务时,我可以从ServiceSecurityContext.Current.WindowsIdentity.Name获取用户的Windows名称。 In the second service, that doesn't work and ServiceSecurityContext.Current.WindowsIdentity.Name is just IIS APPPOOL\\DefaultAppPool . 在第二个服务中,该服务无效,并且ServiceSecurityContext.Current.WindowsIdentity.Name只是IIS APPPOOL\\DefaultAppPool

I configured the WsDualHttpBinding to use windows authentication, but that didn't help. 我将WsDualHttpBinding配置为使用Windows身份验证,但这没有帮助。 Here is the server-side configuration: 这是服务器端配置:

<wsDualHttpBinding>
  <binding name="internalHttpBinding">
    <security mode="Message">
      <message clientCredentialType="Windows"/>
    </security>
  </binding>
</wsDualHttpBinding>

And here's the code in the first service to establish communication with the second service: 这是第一个服务中与第二个服务建立通信的代码:

private WSDualHttpBinding binding = new WSDualHttpBinding();
private ChannelFactory<IMyService> factory;
public IMyService Contract { get; set; }
public MyServiceCallback Callback { get; set; }

public MyService(Uri uri)
{
    EndpointAddress address = new EndpointAddress(uri);
    Callback = new MyServiceCallback();
    var instanceContext = new InstanceContext(Callback);

    binding.Security.Mode = WSDualHttpSecurityMode.Message;
    binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;

    factory = new DuplexChannelFactory<IMyService>(instanceContext, binding, address);
    factory.Credentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
    factory.Credentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
    Contract = factory.CreateChannel();

    // Call operations on Contract
}

How can I configure the first service to pass on the user's identity to the second service? 如何配置第一个服务以将用户身份传递给第二个服务?

This seems to be a problem with pass-through authentication. 传递身份验证似乎是一个问题。 First, you need to be in a Active Directory environment. 首先,您需要处于Active Directory环境中。 Kerberos must be used for authentication, NTLM will not work. 必须使用Kerberos进行身份验证,NTLM无法正常工作。 You can use klist to check this: https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/klist 您可以使用klist进行检查: https : //docs.microsoft.com/zh-cn/windows-server/administration/windows-commands/klist

Also see https://blogs.msdn.microsoft.com/besidethepoint/2010/05/08/double-hop-authentication-why-ntlm-fails-and-kerberos-works/ for an explanation. 另请参阅https://blogs.msdn.microsoft.com/besidethepoint/2010/05/08/double-hop-authentication-why-ntlm-fails-and-kerberos-works/以获取解释。

May be this SO article can help: 可能这篇文章可以帮助您:

Pass Windows credentials to remote https WCF service 将Windows凭据传递到远程https WCF服务

And this: https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/delegation-and-impersonation-with-wcf 这是: https : //docs.microsoft.com/zh-cn/dotnet/framework/wcf/feature-details/delegation-and-impersonation-with-wcf

After the server-side enables impersonation and the client-side has set up the windows credential, 在服务器端启用模拟并且客户端设置了Windows凭据之后,

ServiceReference1.ServiceClient client = new ServiceReference1.ServiceClient();
            client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
            client.ClientCredentials.Windows.ClientCredential.UserName = "Test";
            client.ClientCredentials.Windows.ClientCredential.Password = "123456";

We could retrieve the running Windows account by using the below code. 我们可以使用以下代码来检索正在运行的Windows帐户。

if (ServiceSecurityContext.Current.WindowsIdentity.ImpersonationLevel == TokenImpersonationLevel.Impersonation ||
    ServiceSecurityContext.Current.WindowsIdentity.ImpersonationLevel == TokenImpersonationLevel.Delegation)
{
    using (ServiceSecurityContext.Current.WindowsIdentity.Impersonate())
    {
        Console.WriteLine("Impersonating the caller imperatively");
        Console.WriteLine("\t\tThread Identity            :{0}",
    WindowsIdentity.GetCurrent().Name);
        Console.WriteLine("\t\tThread Identity level  :{0}",
             WindowsIdentity.GetCurrent().ImpersonationLevel);
        Console.WriteLine("\t\thToken                     :{0}",
             WindowsIdentity.GetCurrent().Token.ToString());
    }
}

Please refer to the below example. 请参考以下示例。
https://docs.microsoft.com/en-us/dotnet/framework/wcf/samples/impersonating-the-client https://docs.microsoft.com/en-us/dotnet/framework/wcf/samples/impersonating-the-client
https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/delegation-and-impersonation-with-wcf https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/delegation-and-impersonation-with-wcf
Feel free to let me know if there is anything I can help with. 请随时告诉我是否有什么我可以帮助的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM