基于 SSL 的 WCF - 404 错误

Posted

技术标签:

【中文标题】基于 SSL 的 WCF - 404 错误【英文标题】:WCF over SSL - 404 error 【发布时间】:2010-12-04 00:21:45 【问题描述】:

好的,我一定错过了一些非常简单的东西,因为我已经搜索了好几天,在那里查看了几十个答案,在这里,我就是无法让它工作,不管我是什么'我试过了。当通过普通 HTTP 调用时,该服务工作得非常好。

这是我们的设置...我们有一个域 http://www.mydomain.com 。我们从 thawte 在该域上安装了 SSL 证书,就像我们保护电子商务网站一样。这一切都很好,我可以去 https://www.mydomain.com 并且它工作正常。 我在 Windows Server 2003 R2 上运行 VS2008、.NET 3.5 站点。

现在,我向我的网站添加了启用 Silverlight 的 WCF 服务,我想通过 SSL 与之通信。如果我浏览到 https://www.mydomain.com/myservice.svc,它会按预期显示 WSDL 描述性“您已创建服务”页面,显示使用

创建您的客户端
svcutil.exe https:// ... 

编辑: 我意识到 wsdl 文件中为 svcutil 显示的 url 实际上指向 Web 服务器的物理框名称,而不是正确的域。所以我通过 this blog posting 中显示的步骤使用 adsutil 脚本在 IIS 中更新网站的 SecureBinding。现在 wsdl 文件显示了正确的 SSL 地址,但我仍然得到同样的错误。

现在我尝试将我的 Silverlight 应用程序连接到它,但它不起作用,在异步调用的结果中返回异常,说明“远程服务器返回错误:NotFound。我读过的一些博客都谈到了通过创建一个测试 Windows 应用程序并尝试从中引用它来将其缩小到 Silverlight 问题。好吧,我做到了,甚至在一个常规的 Windows 应用程序中尝试访问通过 SSL 服务我得到一个异常说明:

System.ServiceModel.EndpointNotFoundException: 
There was no endpoint listening at https://www.mydomain.com/mysubdir/myservice.svc that could accept the message. 
This is often caused by an incorrect address or SOAP action. 
See InnerException, if present, for more details. ---> 
System.Net.WebException: The remote server returned an error: (404) Not Found.
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

尽管我使用 HTTPS 方案明确地将服务引用添加到 Windows 应用程序,并且它正确获取所有方法并在编辑器中的 Intellisense 中显示它们。

请注意,这是一项不需要用户明确登录的服务。我将在我的 SOAP 信封中发送自定义标头以验证请求是否来自我们的应用程序,并且我只想防止掠夺者嗅探线路并挑选出自定义标头。

现在到代码,我必须只是有一些愚蠢的小设置错误,因为从我读过的所有内容来看,这应该是一个相当简单的练习。

首先,我的服务的代码隐藏类装饰有以下属性:

<ServiceBehavior(AddressFilterMode:=AddressFilterMode.Any)> 
<AspNetCompatibilityRequirements(RequirementsMode:=AspNetCompatibilityRequirementsMode.Allowed)>

服务器上我的 web.config 的 ServiceModel 部分如下所示:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="basicHttpBinding">
                <security mode="Transport">
                    <transport clientCredentialType ="None"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior name="standingsBehavior">
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
                    <serviceDebug includeExceptionDetailInFaults="false"/>
                </behavior>
            </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true">
        <baseAddressPrefixFilters>
            <add prefix="http://www.mydomain.com:80"/>
        </baseAddressPrefixFilters>
    </serviceHostingEnvironment>
    <services>
        <service behaviorConfiguration="standingsBehavior" name="lijslwebdata">
            <endpoint address="" binding="basicHttpBinding" contract="lijslwebdata"/>
            <!--<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>-->
        </service>
    </services>
</system.serviceModel>

我的 Windows 应用程序中 app.config 的 ServiceModel 部分如下所示:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_lijslwebdata" closeTimeout="00:01:00"
                openTimeout="00:01:00" receiveTimeout="00:10:00" 
                sendTimeout="00:01:00" allowCookies="false" 
                bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                maxBufferSize="65536" maxBufferPoolSize="524288" 
                maxReceivedMessageSize="65536" messageEncoding="Text" 
                textEncoding="utf-8" transferMode="Buffered"
                useDefaultWebProxy="true">
                <readerQuotas maxDepth="32" maxStringContentLength="8192"
                    maxArrayLength="16384"
                    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <security mode="Transport">
                    <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
                    <message clientCredentialType="UserName" algorithmSuite="Default" />
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="https://www.mydomain.com/mysubdir/myservice.svc"
            binding="basicHttpBinding" 
            bindingConfiguration="BasicHttpBinding_lijslwebdata"
            contract="xdata.lijslwebdata" name="BasicHttpBinding_lijslwebdata" />
    </client>
</system.serviceModel>

【问题讨论】:

一个问题,baseAddressPrefixFilters 是否需要以某种方式设置为 HTTPS?? 我也对这个很感兴趣。我目前有一个 HTTP WCF 服务,并且在提供 HTTPS 选项时会遇到麻烦。请记得发布您的结果! :) 【参考方案1】:

我也遇到了同样的问题。您的帖子帮助我弄清楚了问题所在。这是我的服务模型部分。我发现键是 httpsGetEnabled 然后设置 bindingconfiguration 我希望这会有所帮助。

<system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="RequestImageBehavior">
                    <serviceMetadata **httpsGetEnabled**="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                  <dataContractSerializer maxItemsInObjectGraph="1073741824" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <services>
            <service behaviorConfiguration="RequestImageBehavior" name="RequestImage">
                <endpoint address="" 
                          binding="wsHttpBinding" 
                          **bindingConfiguration**="HttpsBinding"
                          contract="IRequestImage">
                </endpoint>
                <endpoint address="mex" 
                          binding="mexHttpBinding" 
                          contract="IMetadataExchange" />
            </service>
        </services>
      <bindings>
        **<wsHttpBinding>
          <binding name="HttpsBinding">
            <security mode="Transport">
              <transport clientCredentialType="None"/>
            </security>
          </binding>
        </wsHttpBinding>**
      </bindings>
    </system.serviceModel>

【讨论】:

我的分辨率相同。我发现我的 bindingConfiguration 没有设置,但我的 bindingName 是。一旦我设置了绑定配置,事情就会开始正常工作。谢谢! 这为我解决了这个问题,但我不得不将 &lt;wsHttpBinding&gt; 重命名为 &lt;webHttpBinding - 也许 .NET 版本有所不同? theyetiman,查看此链接了解 wsHttpBinding 和 webHttpBinding 之间的区别。完全不同的球赛。 ***.com/questions/2650785/…【参考方案2】:

我最近正在处理这个问题,并想添加一个调整。如果您按照上述说明操作,您将能够让服务使用 HTTPS,但不能同时使用 HTTP 和 HTTPS。为此,您需要有两个端点配置节点,每个协议一个如下:

 <service name="MyCompany.MyService" >
    <endpoint address="" behaviorConfiguration="AspNetAjaxBehavior"
      binding="webHttpBinding" contract="MyCompany.MyService" bindingConfiguration="sslBinding" />
    <endpoint address="" behaviorConfiguration="AspNetAjaxBehavior"
      binding="webHttpBinding" contract="MyCompany.MyService" />
  </service>

(取自我的代码库,酌情调整行为配置和绑定)

【讨论】:

谢谢!!我实际上发现我的 HTTPS 上的 SSL 服务返回了一个没有 HTTP 端点的 404。添加 HTTP 端点修复了它。可笑。【参考方案3】:

我花了几个小时才发现我的问题是服务名称

<services>
      <service name="TimberMill.Web.Data.LogReceiverService">
        <endpoint binding="basicHttpBinding" bindingConfiguration="basicBinding"
                     contract="NLog.LogReceiverService.ILogReceiverServer" />
      </service>
    </services>

必须与我的 *.svc 文件中的类似条目完全匹配。

<%@ ServiceHost 
    Language="C#" 
    Debug="true" 
    Service="TimberMill.Web.Data.LogReceiverService, TimberMill.Web"
    Factory="Autofac.Integration.Wcf.AutofacServiceHostFactory, Autofac.Integration.Wcf"
    CodeBehind="LogReceiverService.svc.cs" 
%>

我不确定这是否与我使用 Autofac 有关。 在纯 HTTP 下一切正常。 但是在 HTTPS 下失败。

好吧,我想是的,我现在不想通过更详细的测试来打扰任何事情,以免我激怒 WCF-Config 之神并且我的配置再次中断。 YMMV。

【讨论】:

是的 serviceName 为我解决了这个问题【参考方案4】:

在我的情况下,这些答案都没有帮助。

相反,我需要add a duplicate &lt;binding&gt; section that has no name attribute set。

这是我的服务的 web.config 文件的相应部分的转储:

<behaviors>
    <serviceBehaviors>
        <behavior name="ServiceBehaviour">
            <serviceMetadata 
                httpsGetEnabled="true" 
                httpsGetUrl="RemoteSyncService.svc"
                httpGetBindingConfiguration="bindingConfig" />
            <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
        <behavior name="">
            <serviceMetadata 
                httpsGetEnabled="true" 
                httpsGetUrl="RemoteSyncService.svc" />
            <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
    </serviceBehaviors>
</behaviors>

<bindings>
  <basicHttpBinding>
    <binding name="bindingConfig" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" transferMode="Streamed">
        <security mode="Transport">
          <transport clientCredentialType="None"/>
        </security>
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
    </binding>

    <!-- Add binding with EMPTY/MISSING name, see https://forums.iis.net/t/1178173.aspx -->
    <binding maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" transferMode="Streamed">
        <security mode="Transport">
          <transport clientCredentialType="None"/>
        </security>
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
    </binding>
  </basicHttpBinding>
</bindings>

我确实希望有一天这对某人有所帮助。

【讨论】:

只是为了验证这篇文章,这是唯一对我有用的建议【参考方案5】:

我遇到了同样的问题,花了一天时间解决了这个问题。最后,下面的配置使我可以进行 HTTPS 访问。

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="basicHttpBinding">
            </binding>
            <binding name="basicHttpsBinding">
                <security mode="Transport">
                    <transport clientCredentialType ="None"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior name="standingsBehavior">
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true">
        <baseAddressPrefixFilters>
            <add prefix="http://www.mydomain.com/"/>
        </baseAddressPrefixFilters>
    </serviceHostingEnvironment>
    <services>
        <service behaviorConfiguration="standingsBehavior" name="lijslwebdata">
            <endpoint address="" binding="basicHttpBinding" contract="lijslwebdata"/>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
        <service behaviorConfiguration="standingsBehavior" name="sslwebdata">
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpsBinding" contract="sslwebdata"/>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
    </services>
</system.serviceModel>

【讨论】:

【参考方案6】:

一切似乎都很有效,根本没有明显的错误......

只有一个观察/问题:您的 *.svc 文件在哪里??

在错误消息中,我看到:

 https://www.mydomain.com/myservice.svc 

您的 *.svc 文件真的在您网站的***虚拟目录中吗?

通常,*.svc 文件位于 IIS 上的虚拟目录中,因此地址类似于:

 https://www.mydomain.com/YourVirtualDirectory/myservice.svc 

当然,您可以将 ASP.NET 应用程序和 WCF 服务 *.svc 文件部署到 IIS 的根目录 - 但根据我的经验,这并不常见。

只是要检查的东西.....

马克

【讨论】:

是的,不,服务实际上是在一个子目录中。出于安全目的,我只是重命名了路径。我想我应该在假路径中放入一个子目录,但不,它在一个子目录中。【参考方案7】:

好的,我显然解决了这个问题,但我完全不知道为什么/如何。

这就是我所做的。

我添加了一个全新的 EMPTY Silverlight 启用 WCF 服务 然后我更新了 web.config 以反映这两个服务 然后,我实际上只是将有关第一个服务的所有内容复制并粘贴到第二个服务中,但名称除外。

为什么要修复它,我完全不知道。

任何人的 FWIW,这是我的新 web.config ServiceModel 部分,其中包含第二个服务...

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="basicHttpBinding">
            </binding>
            <binding name="basicHttpsBinding">
                <security mode="Transport">
                    <transport clientCredentialType ="None"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior name="standingsBehavior">
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true">
        <baseAddressPrefixFilters>
            <add prefix="http://www.mydomain.com/"/>
        </baseAddressPrefixFilters>
    </serviceHostingEnvironment>
    <services>
        <service behaviorConfiguration="standingsBehavior" name="lijslwebdata">
            <endpoint address="" binding="basicHttpBinding" contract="lijslwebdata"/>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
        <service behaviorConfiguration="standingsBehavior" name="sslwebdata">
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpsBinding" contract="sslwebdata"/>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
    </services>
</system.serviceModel>

【讨论】:

... 这让我充满了与 WCF/Silverlight 其他部分相同的恐惧。变数太多。从头开始创建一个新项目,它将“正常工作”。在现实世界中不是一个选择! (我以前必须这样做)。谢谢你的回答。 我同意,...虽然我的问题与 Silverlight 无关,因为即使我的测试 Windows 客户端最初也无法连接。这完全是 WCF over SSL 的一部分。但我同意......我不喜欢自动修复自己的东西。这是一项不错的技术,只是需要不那么脆弱。【参考方案8】:

几个答案让我重新配置我的 web.config 以包含两个端点。我最终得到了以下 Web.config。

<system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="basicHttpBinding">
        </binding>
        <binding name="basicHttpsBinding">
          <security mode="Transport">
            <transport clientCredentialType ="None"/>
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="standingsBehavior">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
      <baseAddressPrefixFilters>
        <add prefix="http://www.myhost.com"/>
      </baseAddressPrefixFilters>
    </serviceHostingEnvironment>

    <services>
      <service behaviorConfiguration="standingsBehavior" name="NameSpace.ClassName">
        <endpoint address="" binding="basicHttpBinding" contract="NameSpace.ContractInterfaceName"/>
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpsBinding" contract="NameSpace.ContractInterfaceName"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
  </system.serviceModel>

【讨论】:

【参考方案9】:

之前它对您不起作用,因为您将 basicHttpBinding 配置命名为 basicHttpBinding,但没有在 &lt;service&gt; 标记中使用 bindingConfiguration="basicHttpBinding" 引用该配置

在通过添加另一个服务配置确实起作用的更改中,您确实引用了包含 &lt;security&gt; 节点的绑定配置,因此导致它起作用。

【讨论】:

【参考方案10】:

检查您是否遇到与 OP 相同的 404 错误只是另一件事。我摆弄了很多东西,但最终解决方案归结为仅将命名空间添加到我的服务 web.config。

所以普通的旧 ServiceFoo 和 IServiceFoo 不起作用:

  <services>
     <service behaviorConfiguration="quuxBehavior" name="ServiceFoo">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpsBinding" contract="IServiceFoo"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
     </service>
  </services>

但是添加命名空间(ProjectBar)确实有效:

  <services>
     <service behaviorConfiguration="quuxBehavior" name="ProjectBar.ServiceFoo">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpsBinding" contract="ProjectBar.IServiceFoo"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
     </service>
  </services>

【讨论】:

以上是关于基于 SSL 的 WCF - 404 错误的主要内容,如果未能解决你的问题,请参考以下文章

带有 WCF 调用的 Ajax 返回 404 错误

简单的 WCF 服务抛出 404 not found 错误

无法在 IIS 中正确托管 WCF 服务。错误 404

WCF 休息 WebInvoke 获取方法不起作用返回 404 错误

IIS内部署WCF服务出错:HTTP 错误 404.3 - Not Found

部署的 WCF Silverlight 应用程序返回 404 错误