65.9K
CodeProject 正在变化。 阅读更多。
Home

WCF FAQ: 第三部分 – 10 个安全相关 FAQ

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (72投票s)

2009年5月26日

CPOL

19分钟阅读

viewsIcon

332460

downloadIcon

2744

十个安全相关常见问题解答。

这个 10 分钟的短视频解释了如何在 WCF 服务中使用 SSL 实现传输安全。

目录

引言和目标

在本文中,我们将从传输安全和消息安全理解开始。然后,我们将看到使用 WsHTTP 绑定实现传输安全和消息安全的简单代码示例。我们还将通过一个简单的代码示例来看出“BasicHttpBinding”和“WsHttpBinding”之间的区别。WCF 安全本身是一个庞大的主题,但我相信通过本文,您将能够快速入门 WCF 安全。

其他 FAQ 文章

  • WCF FAQ 第一部分:这是一个包含 20 个问题的初学者 FAQ,解释了 WCF 的基本概念,如终结点、契约和绑定。它还讨论了 WCF 服务的各种托管方法。文章最后讨论了 WCF 中的绑定和单向操作。
  • WCF FAQ 第二部分:本 FAQ 包含 10 个问题,涉及双工契约、在不同协议上托管 WCF、MSMQ 绑定、事务隔离级别和双向通信等概念。文章最后讨论了两个队列:易失性队列和死信队列。
  • LINQ FAQ 第一部分:LINQNewbie.aspx
  • LINQ FAQ 第二部分:LINQFAQPart2
  • LINQ FAQ 第三部分:LINQ FAQ 第三部分

WCF 解决的核心安全功能有哪些?

WCF 解决了四个核心安全功能:

  • 机密性:此功能确保信息在从发送者到接收者的传输过程中不会落入错误的人手中。
  • 完整性:此功能确保消息的接收者收到发送者发送的相同信息,没有数据篡改。
  • 身份验证:此功能验证发送者是谁,接收者是谁。
  • 授权:此功能验证用户是否有权执行从应用程序请求的操作。

什么是传输级别和消息级别安全?

当我们谈论 WCF 安全时,有两个方面。第一个是数据,第二个是数据传输的媒介,即协议。WCF 能够应用传输级别(即协议级别)的安全,也能应用消息级别(即数据)的安全。

图:传输和消息级别安全

传输级别安全发生在通道级别。传输级别安全最容易实现,因为它发生在通信级别。WCF 使用 TCP、HTTP、MSMQ 等传输协议,每种协议都有自己的安全机制。HTTPS 是传输级别安全的一种常见实现。HTTPS 在 HTTP 协议之上实现,SSL 提供安全机制。不需要代码更改,这更多的是利用协议提供的现有安全机制。

消息级别安全是通过消息数据本身来实现的。因此,它独立于协议。消息级别安全的一种常见方法是使用某种标准加密算法加密数据。

对于哪些绑定支持传输、消息和混合模式?

注意:下表摘自书籍《Pro WCF: Practical Microsoft SOA Implementation》-- Chris Peiris 和 Denis Mulder – Apress 2007。

下表显示了每种绑定支持的模式。我们不讨论混合模式。它不过是传输模式和消息模式的组合。例如,使用 HTTPS 加密并通过 WsHttp 传输的数据就是混合模式安全。加密就是消息安全,HTTPS 是传输模式。两者结合就构成了混合模式。

数据绑定。 传输模式? 消息模式? 混合模式?
BasicHttpBinding
WsHttpBinding
WsDualHttpBinding
NetTcpBinding
NetNamedPipeBinding
NetMsmqBinding
MsmqIntegrationBinding

那么传输与消息安全的场景、优点和缺点是什么?

  传输 Message
何时应使用其中一种的场景

当两者之间没有中间系统时,这是最佳方法。

如果是内网类型的解决方案,这是最推荐的方法。

当存在中间系统(如另一个 WCF 服务)并且消息通过该系统路由时,消息安全是最佳选择。
优点
  • 不需要额外的编码,因为它使用了协议固有的安全性。
  • 性能更好,因为我们可以使用硬件加速器来提高性能。
  • 互操作性支持广泛,并且通信客户端不需要理解 WS 安全,因为它内置于协议本身。
  • 提供端到端安全,因为它不依赖于协议。网络中的任何中间跳转都不会影响应用程序。
  • 支持广泛的安全选项,因为它不依赖于协议。我们也可以实现自定义安全。
缺点
  • 由于它是协议实现的安全性,因此它只能点对点工作。
  • 由于安全性依赖于协议,因此它具有有限的安全支持,并受限于协议的安全限制。
  • 需要应用程序重构才能实现安全。
  • 由于每条消息都经过加密和签名,因此存在性能问题。
  • 不支持与旧的 ASMX Web 服务互操作。

图:路由路径

你能解释一下如何实现传输安全的一个简单示例吗?

让我们做一个简单的示例,演示如何使用 WsHttp 绑定和 HTTPS 安全来实现传输安全。

步骤 1:使用 WCF 项目创建简单的服务

第一步是创建一个简单的 WCF 项目。因此,单击“新建项目”并选择“WCF 服务项目”。默认情况下,WCF 项目会创建一个默认函数 `GetData()`。我们将在此示例中使用相同的函数。

public class Service1 : IService1
{
    public string GetData(int value)
    {
        return string.Format("You entered: {0}", value);
    }
    public CompositeType GetDataUsingDataContract(CompositeType composite)
    {
        if (composite.BoolValue)
        {
            composite.StringValue += "Suffix";
        }
        return composite;
    }
}

步骤 2:在服务的 web.config 文件中启用传输级别安全

下一步是为 WsHttp 绑定启用传输安全。这可以通过 `Security` XML 标签来完成,如下面的代码片段所示。

<bindings>
    <wsHttpBinding>
        <binding name="TransportSecurity">
            <security mode="Transport">
                <transport clientCredentialType="None"/>
            </security>
        </binding>
    </wsHttpBinding>
</bindings>

步骤 3:绑定绑定并指定 HTTPS 配置

我们现在需要将绑定与终结点关联起来。因此,使用 `bindingConfiguration` 标签指定绑定名称。我们还需要指定托管服务的地址。请注意地址标签中的 HTTS。

将第二个终结点中的 `mexHttpBinding` 更改为 `mexHttpsBinding`。

<service name="WCFWSHttps.Service1" behaviorConfiguration="WCFWSHttps.Service1Behavior">
<!-- Service Endpoints -->
<endpoint address="https:///WCFWSHttps/Service1.svc" 
  binding="wsHttpBinding" bindingConfiguration="TransportSecurity" 
  contract="WCFWSHttps.IService1"/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>

在 `serviceMetadata` 中,我们也需要将 `httpGetEnabled` 更改为 `httpsGetEnabled`。

<serviceBehaviors>
........
.........
<serviceMetadata httpsGetEnabled="true"/>
.........
.........
</serviceBehaviors>

步骤 4:使 Web 应用程序支持 HTTPS

现在我们已经完成了 WCF 服务项目创建和必要的配置更改,是时候编译 WCF 服务项目并将其托管在启用了 HTTPS 的 IIS 应用程序中了。

我们将使用 ‘makecert.exe’,这是 Microsoft 提供的一个免费工具,用于启用 HTTPS 进行测试。MakeCert (Makecert.exe) 是一个命令行工具,它创建一个由系统测试根密钥或其他指定密钥签名的 X.509 证书。该证书将证书名称与密钥对的公钥部分绑定。证书保存在文件中、系统证书存储中,或两者兼有。

您可以从 *C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin* 获取它,或者您也可以从 Windows SDK 获取它。

您可以在 DOS 提示符下输入以下命令,位于“*C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin*”。请注意,“compaq-jzp37md0”是服务器名称,您需要将其替换为您自己的 PC 名称。

makecert -r -pe -n "CN= compaq-jzp37md0 " -b 01/01/2000 
  -e 01/01/2050 -eku 1.3.6.1.5.5.7.3.1 -ss my -sr localMachine -sky exchange 
  -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12

如果您在命令提示符下运行相同的命令,您应该会看到如下所示的“Succeeded”消息。

现在是时候将此证书分配给您的 IIS 网站了。因此,转到 IIS 属性,单击“目录安全性”选项卡,您应该会看到“服务器证书”选项卡。

单击“服务器证书”选项卡,然后按照 IIS 证书向导进行操作。从向导中单击“分配现有证书”。

您可以看到证书列表。“compaq-jzp37md0”证书是我们刚刚使用‘makecert.exe’创建的。

现在尝试在不使用‘https’的情况下测试站点,您将看到如下错误……这意味着您的证书正在工作。

不要忘记启用 IIS 匿名访问。

步骤 5:在 Web 应用程序中调用服务

现在该在 ASP.NET Web 应用程序中调用服务应用程序了。因此,单击“添加服务引用”并指定您的服务 URL。您将看到一个警告框,如下图所示。当我们使用 makecert.exe 时,我们没有在服务 URL 中指定主机名。所以,尽管忽略它。

步骤 6:忽略 HTTPS 错误

makecert.exe’创建测试证书。换句话说,它不是由 CA 签名的。因此,我们需要在我们的 ASP.NET 客户端消费者中忽略这些错误。所以我们创建一个名为 `IgnoreCertificateErrorHandler` 的函数,该函数即使有错误也会返回 true。此函数作为回调附加到 `ServicePointManager.ServerCertificateValidationCallback`。

在同一代码中,您还可以看到调用 `GetData` 函数的服务消费代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using WebApplicationConsumer.ServiceReference1;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

namespace WebApplicationConsumer
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            ServicePointManager.ServerCertificateValidationCallback = 
               new RemoteCertificateValidationCallback(IgnoreCertificateErrorHandler); 
            Service1Client obj = new Service1Client();
            Response.Write(obj.GetData(12));
        }
        public static bool IgnoreCertificateErrorHandler(object sender, 
          X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }
    }
}

步骤 7:享受成功

现在进入最简单的步骤,编译您的 ASP.NET 客户端并享受成功。

你能展示一个简单的消息级别安全示例吗?

让我们做一个简单的示例,使用 WsHTTP 和 X509 证书来实现消息安全。

步骤 1:创建客户端和服务器证书

使用 makecert.exe 创建两个证书,一个用于服务器,一个用于客户端。您可以从“C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin”文件夹获取 makecert.exe。您可以转到 DOS 提示符并运行以下命令:

makecert.exe -sr CurrentUser -ss My -a sha1 -n CN=WCfServer -sky exchange -pe
makecert.exe -sr CurrentUser -ss My -a sha1 -n CN=WcfClient -sky exchange -pe

以下是对 makecert.exe 中指定各个属性的详细解释。

Attribute 解释
-sr

指定证书存储的注册表位置。SubjectCertStoreLocation 参数必须是以下之一:

  • currentUser - 指定注册表位置 HKEY_CURRENT_USER。
  • localMachine - 指定注册表位置 HKEY_LOCAL_MACHINE。
-ss 指定存储生成证书的证书存储名称。
-a 指定算法。可以是 MD5 或 SHA1。
-n 为证书指定名称。此名称必须符合 X.500 标准。最简单的方法是使用“CN=MyName”格式。如果未指定 /n 开关,则证书的默认名称为“Joe's Software Emporium”。
-sky 指定密钥类型。可以是 exchange 或 signature。
-pe 这使得密钥可导出。

注意Makecert.exe 是 Microsoft 提供的免费工具,有助于创建由系统测试根密钥或其他指定密钥签名的 X.509 证书。这是测试证书,不是真实的,不应用于生产环境。对于生产环境,请从 Thawte、Verisign、GeoTrust 等处购买合适的证书。

目前我们指定了希望使用‘WcfClient’名称创建客户端密钥,使用‘WCFServer’名称创建服务器密钥。证书应为当前用户创建,并且应该是可导出的。

运行命令后,您应该会看到如下所示的“Succeeded”消息。该图显示了为服务器和客户端创建的密钥。

步骤 2:将证书复制到受信任的人员证书中

转到“开始”->“运行”,键入 MMC 并按 Enter。您将看到 MMC 控制台。单击“文件”->“添加/删除管理单元”。

您将看到“添加/删除管理单元”对话框,单击“添加”按钮,选择“证书”,然后选择“我的用户帐户”。您可以在“个人证书”文件夹中看到为客户端和服务器创建的证书。我们需要将这些证书复制到“受信任的人员”->“证书”文件夹中。

步骤 3:在 WCF 服务 web.config 文件中指定证书路径和模式

既然我们已经创建了两个证书,我们就需要将这些证书引用到我们的 WCF 项目中。所以我们创建了两个项目,一个包含 WCF 服务,另一个是用于消费 WCF 服务的 Web 应用程序。

让我们打开 WCF 服务的 web.config 文件并输入两项重要内容:

  • 证书存储位置和 WCF 应用程序如何找到它。这是使用 `serviceCertificate` 标签定义的,如下面的代码片段所示。
  • certificationvalidationmode 定义了如何验证客户端证书。
证书验证模式 描述
链信任 在这种情况下,客户端证书会针对根证书进行验证。
同级信任 PeerTrust 确保证书的公钥部分位于客户端计算机的“受信任的人员”证书文件夹中。
ChainORPeertrust 这只是链式信任和同级信任的 OR 条件。

以上两点被合并并在 WCF 服务的 web.config 文件中输入。

<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="PeerTrust"/>
</clientCertificate>
<serviceCertificate findValue="WCfServer"
storeLocation="CurrentUser"
storeName="My"
x509FindType="FindBySubjectName" />
</serviceCredentials>

步骤 4:定义绑定

既然我们已经定义了证书和身份验证类型,我们就需要定义身份验证值将通过证书通过消息发送。您可以看到我们定义了 `WsHttpBinding`,其中消息属性指定 WCF 客户端需要发送证书进行验证。

<bindings>
<wsHttpBinding>
<binding name="wsHttpEndpointBinding">
<security>
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>

步骤 5:将绑定与终结点关联

完成后,我们需要将此绑定与终结点关联起来。这可以通过使用 `bindingConfiguration` 属性来完成,如下面的代码片段所示。

<endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding" 
  contract="WCFServiceCertificate.IService1">

步骤 6:使您的 Web 应用程序成为消费 WCF 服务的客户端

这就是 WCF 服务方面所需的一切。因此,编译 WCF 服务并使用“服务引用”在 ASP.NET Web 应用程序中引用它。下面是引用服务并调用服务 `GetData` 函数的代码片段。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
>using WebConsumer.ServiceReference1;
namespace WebConsumer
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Service1Client obj = new Service1Client();
            Response.Write(obj.GetData(12));
        }
    }
}

现在,如果您尝试运行客户端(即 Web 应用程序),您应该会收到如下错误。错误清楚地表明,在提供客户端证书之前,您无法使用 WCF 服务。

步骤 7:在 WCF 客户端中定义证书

因此,让我们开始在 WCF 客户端中定义证书的过程。我们定义身份验证证书模式和证书路径的方式,同样,我们也需要为 WCF 客户端定义它。您可以看到我们将身份验证模式定义为‘peertrust’,并将客户端证书名称指定为‘WcfClient’。

<behaviors>
<endpointBehaviors>
<behavior name="CustomBehavior">
<clientCredentials>
<clientCertificate findValue="WcfClient" x509FindType="FindBySubjectName" 
          storeLocation="CurrentUser" storeName="My" />
<serviceCertificate>
<authentication certificateValidationMode="PeerTrust"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>

步骤 8:在 WCF 客户端上将行为与终结点关联

我们需要将上述定义的行为与终结点关联起来。您可以看到我们通过 `behaviorConfiguration` 属性绑定了行为。我们还需要指定 DNS 值为 `WcfServer`,即您的服务器证书名称。

<client>
<endpoint address="https://:1387/Service1.svc" binding="wsHttpBinding"
    bindingConfiguration="WSHttpBinding_IService1" contract="ServiceReference1.IService1"
    name="WSHttpBinding_IService1" 
>behaviorConfiguration="CustomBehavior">
<identity>
><dns value="WcfServer" />
</identity>
</endpoint>
</client>

步骤 9:享受您的辛勤劳动

完成后,您可以运行 ASP.NET Web 应用程序,您应该会看到如下显示。

BasicHttpBinding 和 WsHttpBinding 之间有什么区别?

如果用一句话总结‘WsHttpBinding’和‘BasicHttpBinding’的区别,那就是‘WsHttpBinding’支持‘WS-*’规范。WS-* 规范只不过是扩展 Web 服务功能的标准。

下表详细比较了这两个实体在安全性、兼容性、可靠性和 SOAP 版本方面的差异。

标准 BasicHttpBinding WsHttpBinding
安全支持 它支持旧的 ASMX 风格,即 WS-BasicProfile 1.1。 它公开使用 WS-* 规范的 Web 服务。
兼容性 它面向没有安装 .NET 3.0 的客户端,并且支持更广泛的客户端。许多客户端,如 Windows 2000,仍然无法运行 .NET 3.0。因此,较旧版本的 .NET 可以使用此服务。 由于它是使用 WS-* 规范构建的,因此它不支持更广泛的客户端,并且不能被 3.0 以下版本的 .NET 使用。
SOAP 版本 SOAP 1.1 SOAP 1.2 和 WS-Addressing 规范。
可靠消息 不支持。换句话说,如果客户端发起两次或三次调用,您真的不知道它们是否会按相同顺序返回。 支持,因为它支持 WS-* 规范。
默认安全选项 默认情况下,当客户端进行调用时,消息没有提供安全性。换句话说,数据以明文形式发送。 由于 WsHttBinding 支持 WS-*,它默认启用了 WS-Security。因此,数据不是以明文形式发送的。
安全选项
  • Windows – 默认身份验证
  • Basic
  • 证书
  • 传输
  • Message
  • 带消息凭据的传输

您可能注意到的最大区别之一是安全性方面。默认情况下,‘BasicHttpBinding’以明文发送数据,而‘WsHttpBinding’以加密和安全的方式发送。为了演示这一点,让我们创建两个服务,一个使用‘BasicHttpBinding’,另一个使用‘WsHttpBinding’,然后我们更详细地查看安全性方面。

我们将做一个小的示例,看看‘BasicHttpBinding’如何以明文格式发送数据,以及‘WsHttpBinding’如何加密数据。

注意:默认情况下,出于互操作性目的,‘BasicHttpBinding’未启用安全性。换句话说,它就像我们旧的 Web 服务,即 ASMX。但这并不意味着我们不能在‘BasicHttpBinding’中启用安全性。不久前,我写了一篇关于如何在‘BasicHttpBinding’中启用安全性的文章:WCFBasicHttpBinding.aspx

你能展示 BasicHttpBinding 与 WsHttpBinding 之间的安全区别吗?

为了理解这两种实体之间的安全差异,我们将做一个小型项目。在此项目中,我们将创建两个 WCF 服务:一个使用‘BasicHttpBinding’,第二个使用‘WsHttpBinding’。

步骤 1:让我们首先使用‘BasicHttpBinding’创建一个简单的服务。为此,我们只需创建一个简单的 WCF 项目,然后修改‘ServiceModel’元素,如下所示。您可以在‘endpoint’标签中看到,我们已将‘basicHttpBinding’指定为协议。

<system.serviceModel>
<services>
<service name="WCFBasicHttpBinding.Service1" 
   behaviorConfiguration="WCFBasicHttpBinding.Service1Behavior">
<!-- Service Endpoints -->
<endpoint address="" binding="basicHttpBinding" 
  contract="WCFBasicHttpBinding.IService1">
<!-- 
Upon deployment, the following identity element should be removed or replaced to reflect the 
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity 
automatically.
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" 
   contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFBasicHttpBinding.Service1Behavior">
<!-- To avoid disclosing metadata information, set the value below to false 
   and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, 
  set the value below to true. Set to false before deployment 
  to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>

步骤 2:我们需要创建另一个使用‘WsHttpBinding’的服务。为此,您无需做任何特殊操作。默认情况下,WCF 项目是使用‘WsHttpBinding’创建的。下面是 Web.config 文件的样子。您可以看到 endpoint 标签是如何使用‘wsHttpBinding’的。

<system.serviceModel>
<services>
<service name="WCFWsHttpBindingHttps.Service1" 
    behaviorConfiguration="WCFWsHttpBindingHttps.Service1Behavior">
<!-- Service Endpoints -->
<endpoint address="" binding="wsHttpBinding" 
      contract="WCFWsHttpBindingHttps.IService1">
<!-- 
Upon deployment, the following identity element should be removed or replaced to reflect the 
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity 
automatically.
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" 
      contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFWsHttpBindingHttps.Service1Behavior">
<!-- To avoid disclosing metadata information, set the value below to false 
       and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. 
       Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>

步骤 3:我们不会在这两个服务中创建任何新方法。我们只使用 WCF 模板创建的默认代码。这两个服务都有一个 `GetData` 函数,该函数返回一个字符串。`GetData` 是 WCF 项目中创建的默认函数。

public class Service1 : IService1
{
    public string GetData(int value)
    {
        return string.Format("You entered: {0}", value);
    }
    public CompositeType GetDataUsingDataContract(CompositeType composite)
    {
        if (composite.BoolValue)
        {
            composite.StringValue += "Suffix";
        }
        return composite;
    }
}

步骤 4:现在我们的服务已经创建,我们需要创建一个客户端来消费这个服务。我们创建一个简单的 Web 应用程序并添加两个引用:一个服务引用,即‘WsHttpBinding’,以及一个 Web 引用,即‘BasicHttpBinding’。请注意,当您右键单击添加引用时,需要使用“添加服务引用”来添加‘WsHttpService’,而需要为‘BasicHttpBinding’添加 Web 引用。

我们将在默认的 ASPX 页面上添加两个按钮。一个按钮将调用 HTTP 服务,另一个按钮将调用 WsHTTP 服务。下面是在按钮单击事件中调用 `GetData` 的方式。

步骤 5:现在我们的项目准备就绪,是时候嗅探并查看在这两种场景中数据如何在客户端和服务之间传输了。让我们从 http://www.ieinspector.com/httpanalyzer/download.html 下载一个简单的 HTTP 数据记录器。然后,我们将逐个单击这两个按钮,并使用该工具记录数据传输。您可以看到对于 basic HTTP 协议,已发布的数据是简单的纯 XML 格式,而对于 WsHTTP 协议,它是加密格式。

何时应使用 WsHttp 而不是 BasicHttp?

如果您正在寻找向后兼容性并支持大量客户端,那么 basic HTTP 绑定是最佳选择;否则,如果您看到客户端是在 .NET 3.0 及更高版本中创建的,那么 WsHttp 是一个很好的起点。

如何使用‘BasicHttpBinding’在 WCF 上启用 Windows 身份验证?

步骤 1:创建 WCF 服务应用程序项目,如下面的图所示。

圈选 WCF 服务应用程序 -> 选择它

默认情况下,WCF 项目会创建一个类文件,其中包含 `GetData` 函数。此函数接受数字值,并在您输入“1”时显示类似“You entered 1 value”的说明性句子。

public class Service1 : IService1
{
    public string GetData(int value)
    {
        return string.Format("You entered: {0}", value);
    }
}

步骤 2:当我们创建 WCF 服务应用程序时,它还附带一个 web.config 文件。因此,打开 web.config 文件并确保身份验证模式为 Windows。

<authentication mode="Windows" />

步骤 3:第三步是定义绑定和传输类型。要定义绑定,我们需要在 `bindings` XML 标签内输入一个 `basicHttpBinding` 元素。我们还需要将 `clientCredentialType` 定义为 Windows。

<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpEndpointBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
.........
.........
</system.serviceModel>

步骤 4:现在定义的绑定需要与服务接口‘service1’关联。因此,我们需要修改 `services` 元素,如下所示。请注意,我们定义了一个具有绑定关联的终结点。

<system.serviceModel>
........
........
........
<services>
<service behaviorConfiguration="WCFWindowsBasicHttpBinding.Service1Behavior" 
              name="WCFWindowsBasicHttpBinding.Service1">
<endpoint address="" binding="basicHttpBinding"
bindingConfiguration="BasicHttpEndpointBinding"
name="BasicHttpEndpoint" contract="WCFWindowsBasicHttpBinding.IService1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</service>
</services>
.........
.........
.........
.........
</system.serviceModel>

您的 `<system.serviceModel>` XML 以及绑定和服务如下所示:

<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpEndpointBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="WCFWindowsBasicHttpBinding.Service1Behavior" 
              name="WCFWindowsBasicHttpBinding.Service1">
<endpoint address="" binding="basicHttpBinding"
bindingConfiguration="BasicHttpEndpointBinding"
name="BasicHttpEndpoint" contract="WCFWindowsBasicHttpBinding.IService1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFWindowsBasicHttpBinding.Service1Behavior">
<!-- To avoid disclosing metadata information, set the value below to false and 
           remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below 
     to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>

步骤 5:转到 IIS 属性并单击“安全”选项卡,并确保禁用匿名访问,并且仅启用 Windows 身份验证。

步骤 6:我们需要在 IIS 中托管我们的服务。因此,将目录设置为 IIS 应用程序,以便您的服务可以被托管。现在,如果您尝试浏览服务,即 SVC 文件,您会看到它会弹出身份验证授权安全对话框。因此,无法使用 Windows 身份验证执行此服务。

步骤 7:让我们来消费这个 WCF 服务。添加一个 ASP.NET Web 应用程序并添加一个 Web 引用。您将看到一个对话框,如下所示。单击“添加引用”,以便为 WCF 服务生成代理。

在您的页面加载代码中输入以下代码片段。添加命名空间引用并调用 `GetData` 方法。最重要的一步是要注意提供的凭据。`DefaultCredentials` 将当前的 Windows 身份传递给 WCF 服务。

如果您执行该服务,您应该会看到如下显示:

您可以尝试在客户端中注释掉下面的代码,换句话说,我们没有传递任何凭据。

obj.Credentials = System.Net.CredentialCache.DefaultCredentials;

现在,如果您执行,您应该会看到如下错误,表明这是一个未经授权的调用。

如需进一步阅读,请观看下面的面试准备视频和分步视频系列。

© . All rights reserved.