我有一些在特定端口上使用 CustomBinding for HTTP 协议的自托管 WCF 服务。到目前为止,我使用 BinaryMessageEncodingBindingElement 和 HttpTransportBindingElement 没有问题。
现在我需要通过使用 HTTPS 但没有证书来保护更多安全。我切换到 HttpsTransportBindingElement 并将 RequireClientCertificate 设置为 false。
我没有在该端口上安装证书。我通过运行“netsh http show sslcert”进行了检查。
当我尝试将我的服务添加到 WPF 应用程序时出现跟随错误(使用 Chrome 浏览我得到“此网页不可用”):
下载“https://localhost:8080/myhost/myservice.svc”时出错。
底层连接已关闭:发送时发生意外错误。
无法从传输连接读取数据:现有连接被远程主机强行关闭。
远程主机强制关闭现有连接
元数据包含无法解析的引用:“https://localhost:8080/myhost/myservice.svc”。
向“https://localhost:8080/myhost/myservice.svc”发出 HTTP 请求时出错。
这可能是由于在 HTTPS 情况下未使用 HTTP.SYS 正确配置服务器证书。
这也可能是由于客户端和服务器之间的安全绑定不匹配造成的。
底层连接已关闭:发送时发生意外错误。
无法从传输连接读取数据:现有连接被远程主机强行关闭。
远程主机强行关闭现有连接
如果在当前解决方案中定义了服务,请尝试构建解决方案并再次添加服务引用。
这是我的绑定:
private System.ServiceModel.Channels.Binding GetHttpBinding(String pName)
{
System.ServiceModel.Channels.BindingElementCollection elements = new System.ServiceModel.Channels.BindingElementCollection();
System.ServiceModel.Channels.BinaryMessageEncodingBindingElement binaryMessageEncoding = new System.ServiceModel.Channels.BinaryMessageEncodingBindingElement();
binaryMessageEncoding.MessageVersion = System.ServiceModel.Channels.MessageVersion.Default;
binaryMessageEncoding.ReaderQuotas.MaxArrayLength = this._maxArrayLength;
binaryMessageEncoding.ReaderQuotas.MaxBytesPerRead = this._maxBytesPerRead;
binaryMessageEncoding.ReaderQuotas.MaxDepth = this._maxDepth;
binaryMessageEncoding.ReaderQuotas.MaxNameTableCharCount = this._maxNameTableCharCount;
binaryMessageEncoding.ReaderQuotas.MaxStringContentLength = this._maxStringContentLength;
elements.Add(binaryMessageEncoding);
if (this._applyHttps)
{
System.ServiceModel.Channels.HttpsTransportBindingElement transport = new System.ServiceModel.Channels.HttpsTransportBindingElement()
{
MaxBufferSize = this._maxBufferSize,
MaxReceivedMessageSize = this._maxReceivedMessageSize,
AllowCookies = false,
BypassProxyOnLocal = false,
HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
MaxBufferPoolSize = this._maxBufferPoolSize,
TransferMode = TransferMode.Buffered,
UseDefaultWebProxy = true,
ProxyAddress = null,
RequireClientCertificate = false
};
elements.Add(transport);
}
else
{
System.ServiceModel.Channels.HttpTransportBindingElement transport = new System.ServiceModel.Channels.HttpTransportBindingElement()
{
MaxBufferSize = this._maxBufferSize,
MaxReceivedMessageSize = this._maxReceivedMessageSize,
};
elements.Add(transport);
}
System.ServiceModel.Channels.CustomBinding custB = new System.ServiceModel.Channels.CustomBinding(elements);
custB.Name = pName;
custB.SendTimeout = new TimeSpan(0, 2, 0);
return custB;
}
我用这种方法配置服务主机:
private void ConfigureBinaryService(ServiceHost pHost, Type pType, String pServiceName)
{
pHost.AddServiceEndpoint(pType, this.GetHttpBinding(pType.Name), String.Empty);
pHost.AddServiceEndpoint(pType, this.GetNetTcpBinding(pType.Name), String.Empty);
pHost.Description.Endpoints[0].Name = pType.Name + "_BasicBin";
pHost.Description.Endpoints[1].Name = pType.Name + "_TCP";
pHost.OpenTimeout = new TimeSpan(0, 2, 0);
pHost.CloseTimeout = new TimeSpan(0, 2, 0);
System.ServiceModel.Description.ServiceMetadataBehavior metadataBehavior = pHost.Description.Behaviors.Find<System.ServiceModel.Description.ServiceMetadataBehavior>();
if (metadataBehavior == null)
{
metadataBehavior = new System.ServiceModel.Description.ServiceMetadataBehavior();
pHost.Description.Behaviors.Add(metadataBehavior);
}
if (this._applyHttps)
metadataBehavior.HttpsGetEnabled = true;
else
metadataBehavior.HttpGetEnabled = true;
metadataBehavior.MetadataExporter.PolicyVersion = System.ServiceModel.Description.PolicyVersion.Policy15;
if (this._applyHttps)
pHost.AddServiceEndpoint(System.ServiceModel.Description.ServiceMetadataBehavior.MexContractName
, System.ServiceModel.Description.MetadataExchangeBindings.CreateMexHttpsBinding(), "mex");
else
pHost.AddServiceEndpoint(System.ServiceModel.Description.ServiceMetadataBehavior.MexContractName
, System.ServiceModel.Description.MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
pHost.AddServiceEndpoint(System.ServiceModel.Description.ServiceMetadataBehavior.MexContractName
, System.ServiceModel.Description.MetadataExchangeBindings.CreateMexTcpBinding(), this._NetTcpComm + @"/" + pServiceName + @"/mex");
pHost.Description.Endpoints[2].Name = pType.Name + "_mex_BasicBin";
pHost.Description.Endpoints[3].Name = pType.Name + "_mex_TCP";
foreach (var item in pHost.Description.Endpoints[0].Contract.Operations)
item.Behaviors.Find<System.ServiceModel.Description.DataContractSerializerOperationBehavior>().MaxItemsInObjectGraph = System.Int32.MaxValue;
foreach (var item in pHost.Description.Endpoints[1].Contract.Operations)
item.Behaviors.Find<System.ServiceModel.Description.DataContractSerializerOperationBehavior>().MaxItemsInObjectGraph = System.Int32.MaxValue;
System.ServiceModel.Description.ServiceDebugBehavior debugBehavior =
pHost.Description.Behaviors.Find<System.ServiceModel.Description.ServiceDebugBehavior>();
if (debugBehavior == null)
{
debugBehavior = new System.ServiceModel.Description.ServiceDebugBehavior();
pHost.Description.Behaviors.Add(debugBehavior);
}
debugBehavior.IncludeExceptionDetailInFaults = true;
}
当 this._applyHttps 为 false 时,浏览器和 WPF 项目中的引用都可以访问我的服务。
所以我在享受了你这么久的帮助后第一次寻求帮助,没有直接询问。我错过了什么?由于它不是托管在 IIS 下,我是否还需要一个证书才能安装在服务器端仅用于特定端口?
提前谢谢大家!如果有人已经回答了这个案例,我很抱歉没有找到它......