本主题演示如何在驻留于 Windows 域中并由同一域中的客户端调用的 Windows Communication Foundation (WCF) 服务上启用传输安全。有关此方案的更多信息,请参见通过 Windows 身份验证确保的传输安全。有关示例应用程序,请参见 WSHttpBinding 示例。
本主题假定您已定义一个现有的协定接口和实现及其加载项。您还可以修改一个现有的服务和客户端。
您完全可以在代码中使用 Windows 凭据来保护服务。或者,也可以通过使用配置文件省略某些代码。本主题演示了这两种方法。请务必仅使用其中一种方法,而不是同时使用两种方法。
前三个过程演示如何使用代码保护服务。第四个和第五个过程演示如何使用配置文件保护服务。
使用代码
服务和客户端的完整代码位于本主题末尾的“示例”一节中。
第一个过程演练如何在代码中创建和配置 WSHttpBinding 类。该绑定使用 HTTP 传输。在客户端上使用了同一绑定。
创建使用 Windows 凭据和消息安全的 WSHttpBinding
在“示例”一节的服务代码中,将此过程的代码插入到
Test类的Run方法开头。创建 WSHttpBinding 类的一个实例。
将 WsHttpSecurity 类的 Mode 属性设置为 Message。
将 MessageSecurityOverHttp 类的 ClientCredentialType 属性设置为 Windows。
此过程的代码如下:
Dim myBinding As New WSHttpBinding() myBinding.Security.Mode = SecurityMode.Message myBinding.Security.Message.ClientCredentialType = MessageCredentialType.Windows// First procedure: // create a WSHttpBinding that uses Windows credentials and message security WSHttpBinding myBinding = new WSHttpBinding(); myBinding.Security.Mode = SecurityMode.Message; myBinding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
在服务中使用该绑定
这是第二个过程,演示如何在自承载服务中使用该绑定。有关承载服务的更多信息,请参见承载服务。
在服务中使用绑定
在上一过程的代码之后插入此过程的代码。
创建一个名为
contractType的 Type 变量,并为其分配接口类型 (ICalculator)。在使用 Visual Basic 时,请使用 GetType 运算符;在使用 C# 时,请使用 typeof 关键字。创建另一个名为
serviceType的 Type 变量,并为其分配所实现的协定的类型 (Calculator)。使用该服务的基址创建 Uri 类的一个实例,该实例名为
baseAddress。基址必须具有与传输匹配的方案。在本示例中,传输方案为 HTTP,且地址包含特殊的统一资源标识符 (URI)“localhost”和端口号 (8036),以及一个终结点基址(“serviceModelSamples/”):https://localhost:8036/serviceModelSamples/。使用
serviceType和baseAddress变量创建 ServiceHost 类的一个实例。使用
contractType、绑定和终结点名称 (secureCalculator) 将一个终结点添加到服务中。在启动对服务的调用时,客户端必须将基址和终结点名称连接起来。调用 Open 方法以启动该服务。此过程的代码如下所示:
' Create the Type instances for later use and the URI for ' the base address. Dim contractType As Type = GetType(ICalculator) Dim serviceType As Type = GetType(Calculator) Dim baseAddress As New Uri("https://localhost:8036/serviceModelSamples/") ' Create the ServiceHost and add an endpoint, then start ' the service. Dim myServiceHost As New ServiceHost(serviceType, baseAddress) myServiceHost.AddServiceEndpoint(contractType, myBinding, "secureCalculator") myServiceHost.Open()// 2nd Procedure: // Use the binding in a service // Create the Type instances for later use and the URI for // the base address. Type contractType = typeof(ICalculator); Type serviceType = typeof(Calculator); Uri baseAddress = new Uri("https://localhost:8036/SecuritySamples/"); // Create the ServiceHost and add an endpoint, then start // the service. ServiceHost myServiceHost = new ServiceHost(serviceType, baseAddress); myServiceHost.AddServiceEndpoint (contractType, myBinding, "secureCalculator"); //enable metadata ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = true; myServiceHost.Description.Behaviors.Add(smb); myServiceHost.Open();
在客户端中使用该绑定
此过程演示如何生成与服务进行通信的代理。该代理通过 ServiceModel 元数据实用工具 (Svcutil.exe) 生成,该工具使用服务元数据创建该代理。
此过程还创建 WSHttpBinding 类的实例以便与服务进行通信,然后调用服务。
本示例仅使用代码来创建客户端。另一种方法是使用配置文件,如此过程之后的一节所示。
通过代码在客户端中使用绑定
使用 SvcUtil.exe 工具根据服务的元数据生成代理代码。有关更多信息,请参见 如何:创建 Windows Communication Foundation 客户端. 生成的代理代码继承自 ClientBase 类,这确保了每个客户端都具有与 WCF 服务通信所需的构造函数、方法和属性。在本示例中,生成的代码包括
CalculatorClient类,该类实现了ICalculator接口,以便与服务代码兼容。在客户端程序的
Main方法的开头插入此过程的代码。创建 WSHttpBinding 类的一个实例,并且将其安全模式设置为 Message,将其客户端凭据类型设置为 Windows。本示例将变量命名为
clientBinding。创建 EndpointAddress 类的一个实例,该实例名为
serviceAddress。将基址与终结点名称连接起来以初始化该实例。使用
serviceAddress和clientBinding变量创建所生成的客户端类的一个实例。调用 Open 方法,如下面的代码所示。
调用服务并显示结果。
Dim b As New WSHttpBinding(SecurityMode.Message) b.Security.Message.ClientCredentialType = MessageCredentialType.Windows Dim ea As New EndpointAddress("net.tcp://machinename:8036/endpoint") Dim cc As New CalculatorClient(b, ea) cc.Open() ' Alternatively, use a binding name from a configuration file generated by the ' SvcUtil.exe tool to create the client. Omit the binding and endpoint address ' because that information is provided by the configuration file. ' CalculatorClass cc = new CalculatorClient("ICalculator_Binding")// 3rd Procedure: // Creating a binding and using it in a service // To run using config, comment the following lines, and uncomment out the code // following this section WSHttpBinding b = new WSHttpBinding(SecurityMode.Message); b.Security.Message.ClientCredentialType = MessageCredentialType.Windows; EndpointAddress ea = new EndpointAddress("Http://localhost:8036/SecuritySamples/secureCalculator"); CalculatorClient cc = new CalculatorClient(b, ea); cc.Open(); // Now call the service and display the results // Call the Add service operation. double value1 = 100.00D; double value2 = 15.99D; double result = cc.Add(value1, value2); Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result); // Closing the client gracefully closes the connection and cleans up resources. cc.Close();
使用配置文件
如果不用程序代码创建绑定,还可以使用下面所示的配置文件绑定节的代码。
请注意 服务配置文件和客户端配置文件都使用此配置代码。
使用配置在 Windows 域中的服务上启用传输安全
将 <wsHttpBinding> 元素添加到配置文件的 <bindings> 元素节。
将一个 <binding> 元素添加到 <WSHttpBinding> 元素中,并将 configurationName 属性设置为适合于应用程序的值。
添加一个 <security> 元素,并将 mode 属性设置为 Message。
添加一个 <message> 元素,并将 clientCredentialType 属性设置为 Windows。
在服务的配置文件中,使用下面的代码替换 <bindings> 节。如果还没有服务配置文件,请参见使用绑定配置服务和客户端。
<bindings> <wsHttpBinding> <binding name = "wsHttpBinding_Calculator"> <security mode="Message"> <message clientCredentialType="Windows"/> </security> </binding> </wsHttpBinding> </bindings>
在客户端中使用该绑定
此过程演示如何生成两个文件:一个与服务进行通信的代理和一个配置文件。此过程还描述对客户端程序所做的更改,这是在客户端使用的第三个文件。
通过配置在客户端中使用绑定
使用 SvcUtil.exe 工具根据服务的元数据生成代理代码和配置文件。有关更多信息,请参见 如何:创建 Windows Communication Foundation 客户端.
使用上一节中的配置代码替换所生成的配置文件的 <Bindings> 节。
在客户端程序的
Main方法的开头插入程序代码。通过将配置文件中的绑定名称作为输入参数进行传递,创建所生成的客户端类的实例。
调用 Open 方法,如下面的代码所示。
调用服务并显示结果。
// 4th Procedure: // Using config instead of the binding-related code // In this case, use a binding name from a configuration file generated by the // SvcUtil.exe tool to create the client. Omit the binding and endpoint address // because that information is provided by the configuration file. CalculatorClient cc = new CalculatorClient("ICalculator_Binding"); cc.Open(); // Now call the service and display the results // Call the Add service operation. double value1 = 100.00D; double value2 = 15.99D; double result = cc.Add(value1, value2); Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result); // Closing the client gracefully closes the connection and cleans up resources. cc.Close();
示例
using System;
using System.Collections;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Security.Permissions;
[assembly: SecurityPermission(SecurityAction.RequestMinimum, Execution = true)]
namespace Microsoft.Security.Samples
{
public class Test
{
static void Main()
{
Test t = new Test();
Console.WriteLine("Starting....");
t.Run();
}
private void Run()
{
// First procedure:
// create a WSHttpBinding that uses Windows credentials and message security
WSHttpBinding myBinding = new WSHttpBinding();
myBinding.Security.Mode = SecurityMode.Message;
myBinding.Security.Message.ClientCredentialType =
MessageCredentialType.Windows;
// 2nd Procedure:
// Use the binding in a service
// Create the Type instances for later use and the URI for
// the base address.
Type contractType = typeof(ICalculator);
Type serviceType = typeof(Calculator);
Uri baseAddress = new
Uri("https://localhost:8036/SecuritySamples/");
// Create the ServiceHost and add an endpoint, then start
// the service.
ServiceHost myServiceHost =
new ServiceHost(serviceType, baseAddress);
myServiceHost.AddServiceEndpoint
(contractType, myBinding, "secureCalculator");
//enable metadata
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
myServiceHost.Description.Behaviors.Add(smb);
myServiceHost.Open();
Console.WriteLine("Listening");
Console.WriteLine("Press Enter to close the service");
Console.ReadLine();
myServiceHost.Close();
}
}
[ServiceContract]
public interface ICalculator
{
[OperationContract]
double Add(double a, double b);
}
public class Calculator : ICalculator
{
public double Add(double a, double b)
{
return a + b;
}
}
}
另请参见
任务
如何:创建 Windows Communication Foundation 客户端