如何使用Windows身份验证构建https WCF服务器/客户端?

问题描述:

我需要使用https协议构建Windows服务/客户端。应使用客户端提供的用户名/密码在服务器上对用户进行身份验证。我使用TLS加密的传输级保护。该服务是自托管的(没有IIS)。
文档非常模糊,大多数描述只是重复变量的名称而没有解释。此外,我无法找到一个有效的示例。

I need to build a Windows service/client using https protocol. The user should be authenticated on the server using username/password, provided on the client side. I use Transport level protection with TLS encryption. The service is self-hosted (no IIS). Documentation is very vague and most description just repeats the name of the variable with no explanations. Also I was not able to find a functioning example.

我的代码分布在多个函数中。为简单起见,下面是一些我认为与该问题相关的代码片段。请随时询问更多详细信息。

My code is distributed across multiple functions. For simplicity reasons, below are some code snippets that I think relevant to the question. Feel free to ask for more details.

服务器:

private static Binding CreateWebHttpBinding() { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; var binding = new WebHttpBinding(WebHttpSecurityMode.Transport) { ReaderQuotas = _readerQuotas, MaxReceivedMessageSize = 2147483647, OpenTimeout = TimeSpan.MaxValue, CloseTimeout = TimeSpan.MaxValue, SendTimeout = TimeSpan.MaxValue, ReceiveTimeout = TimeSpan.MaxValue, TransferMode = TransferMode.Buffered }; binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows; // I have no idea what Windows actually means - is it the client Windows system or the server Windows?

返回绑定;
}

return binding; }




            var address = new Uri[] {   new Uri($"https://localhost:443/MyApp/{serviceName}.svc") };
            var host = new ServiceHost(serviceType, address);
                var endpoint = host.AddServiceEndpoint(serviceContract, CreateWebHttpBinding(), "");
                endpoint.Behaviors.Add(new WebHttpBehavior { DefaultBodyStyle = WebMessageBodyStyle.Wrapped });

            host.Open();




客户:

                endpointAddress = $"https://{middlewareHost}:443/MyApp/{serviceName}.svc";
                binding = CreateWebHttpBinding(); // same as for the server side
                var channelFactory = new ChannelFactory<T>(binding, new EndpointAddress(new Uri(endpointAddress)));
                if (channelFactory.Credentials != null)
                {
                    channelFactory.Credentials.Windows.ClientCredential =
                        new NetworkCredential(userName, userPassword);
                    channelFactory.Credentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
                    // Here is another totally mysterious setting ^
                }

                ClientCredentials clientCredentials = null;
                foreach (var b in channelFactory.Endpoint.Behaviors)
                {
                    clientCredentials = b as ClientCredentials;
                    if (clientCredentials != null)
                    {
                        break;
                    }
                }

                if (clientCredentials == null)
                {
                    clientCredentials = new ClientCredentials();
                    channelFactory.Endpoint.Behaviors.Add(clientCredentials);
                }

                clientCredentials.UserName.UserName = userName;
                clientCredentials.UserName.Password = userPassword;

                channelFactory.Endpoint.Behaviors.Add(new WebHttpBehavior { DefaultBodyStyle = WebMessageBodyStyle.Wrapped });
channelFactory.CreateChannel()

我正在进行为期两周的工作并完全失败。当我尝试使用http和端口80(传输安全性无)时,我连接,但没有进行身份验证,当我使用https和端口443时,客户端的请求被拒绝,"现有连接
被强行关闭远程主机"。它没有到达我的服务器。我想它被Windows系统拒绝,但由于缺少IIS我不知道 - 如何找到线索。有很多设置,很少或没有文档,没有示例。请
帮助。

I am working on it for two weeks and completely lost. When I try to use http and port 80 (Transport Security None), I get connected, but no authentication happens, when I use https and port 443 the client's request gets rejected with "An existing connection was forcibly closed by the remote host". It does not reach my server. I guess it is rejected by Windows system, but with absence of IIS I don't know - how to find a clue. There are so many settings with little or no documentation and no examples. Please help.

是的,我在服务器端启用了http 80和https 443端口。

And yes, I enabled http 80 and https 443 ports on the server side.

还有一条评论。有些示例使用"WsHttpBinding",而不是"WebHttpBinding"。我实际上尝试过"WsHttpBinding"。除了"WsHttpBinding"之外,它分叉很好。需要直接连接,在互联网上使用
是不可接受的,其中客户端计算机可能位于专用网络中。

One more comment. There are examples that work with "WsHttpBinding", not with "WebHttpBinding". I actually tried "WsHttpBinding" and it forked just fine, except that "WsHttpBinding" requires a direct connection, which is not acceptable for use on the internet, where client computers may be located in a private network.

上述示例还说我需要安装证书:

The aforementioned example also says that I need to install a certificate:

netsh http add sslcert ipport=0.0.0.0:8000 certhash=0000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF}   

但文章没有提到我可以在哪里获得"appid"。看起来有评论在这里和那里有一些重要的信息缺失,这是非常令人沮丧的。

But the article does not mention where I can get the "appid". Looks like there are comments here and there with some important information missing, which is very frustrating.