MessageSecurity 示例 演示如何实现对客户端使用具有 X.509 v3 证书身份验证 WS-Security 的应用程序,并使用服务器的 X.509 v3 证书进行服务器身份验证。 此示例使用默认设置,以便对客户端和服务器之间的所有应用程序消息进行签名和加密。 此示例基于 WSHttpBinding,由 Internet Information Services (IIS)托管的客户端控制台程序和服务库组成。 该服务实现定义请求-回复通信模式的协定。
注意
本示例的设置过程和生成说明位于本主题末尾。
此示例演示如何使用配置控制身份验证,以及如何从安全上下文中获取调用方标识,如以下示例代码所示。
public class CalculatorService : ICalculator
{
public string GetCallerIdentity()
{
// The client certificate is not mapped to a Windows identity by default.
// ServiceSecurityContext.PrimaryIdentity is populated based on the information
// in the certificate that the client used to authenticate itself to the service.
return ServiceSecurityContext.Current.PrimaryIdentity.Name;
}
...
}
该服务公开一个终结点,用于与服务通信,一个终结点用于使用配置文件(Web.config)定义的 WS-MetadataExchange 协议公开服务的 WSDL 文档。 终结点由地址、绑定和协定组成。 绑定使用标准 <wsHttpBinding> 元素进行配置,该元素默认使用消息安全性。 此示例将 clientCredentialType
属性设置为证书以要求客户端身份验证。
<system.serviceModel>
<protocolMapping>
<add scheme="http" binding="wsHttpBinding"/>
</protocolMapping>
<bindings>
<wsHttpBinding>
<!--
This configuration defines the security mode as Message and
the clientCredentialType as Certificate.
-->
<binding>
<security mode ="Message">
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<!--For debugging purposes set the includeExceptionDetailInFaults attribute to true-->
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
<!--
The serviceCredentials behavior allows one to define a service certificate.
A service certificate is used by the service to authenticate itself to its clients and to provide message protection.
This configuration references the "localhost" certificate installed during the setup instructions.
-->
<serviceCredentials>
<serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
<clientCertificate>
<!--
Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate
is in the user's Trusted People store, then it will be trusted without performing a
validation of the certificate's issuer chain. This setting is used here for convenience so that the
sample can be run without having to have certificates issued by a certification authority (CA).
This setting is less secure than the default, ChainTrust. The security implications of this
setting should be carefully considered before using PeerOrChainTrust in production code.
-->
<authentication certificateValidationMode="PeerOrChainTrust" />
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
此行为指定在客户端向服务进行身份验证时使用服务凭据。 服务器证书主题名称是在 findValue
元素中的 < 属性中指定的。
<!--For debugging purposes, set the includeExceptionDetailInFaults attribute to true.-->
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
<!--
The serviceCredentials behavior allows one to define a service certificate.
A service certificate is used by the service to authenticate itself to its clients and to provide message protection.
This configuration references the "localhost" certificate installed during the setup instructions.
-->
<serviceCredentials>
<serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
<clientCertificate>
<!--
Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate
is in the user's Trusted People store, then it will be trusted without performing a
validation of the certificate's issuer chain. This setting is used here for convenience so that the
sample can be run without having to have certificates issued by a certification authority (CA).
This setting is less secure than the default, ChainTrust. The security implications of this
setting should be carefully considered before using PeerOrChainTrust in production code.
-->
<authentication certificateValidationMode="PeerOrChainTrust" />
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
客户端终结点配置由服务终结点、绑定和协定的绝对地址组成。 客户端绑定配置了适当的安全模式和身份验证模式。 在跨计算机方案中运行时,请确保相应地更改服务终结点地址。
<system.serviceModel>
<client>
<!-- Use a behavior to configure the client certificate to present to the service. -->
<endpoint address="http://localhost/servicemodelsamples/service.svc" binding="wsHttpBinding" bindingConfiguration="Binding1" behaviorConfiguration="ClientCertificateBehavior" contract="Microsoft.Samples.Certificate.ICalculator"/>
</client>
<bindings>
<wsHttpBinding>
<!--
This configuration defines the security mode as Message and
the clientCredentialType as Certificate.
-->
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="Certificate"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
...
</system.serviceModel>
客户端实现可以通过配置文件或代码设置要使用的证书。 以下示例演示如何设置在配置文件中使用的证书。
<system.serviceModel>
...
<behaviors>
<endpointBehaviors>
<behavior name="ClientCertificateBehavior">
<!--
The clientCredentials behavior allows one to define a certificate to present to a service.
A certificate is used by a client to authenticate itself to the service and provide message integrity.
This configuration references the "client.com" certificate installed during the setup instructions.
-->
<clientCredentials>
<clientCertificate findValue="client.com" storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName"/>
<serviceCertificate>
<!--
Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate
is in the user's Trusted People store, then it will be trusted without performing a
validation of the certificate's issuer chain. This setting is used here for convenience so that the
sample can be run without having to have certificates issued by a certificate authority (CA).
This setting is less secure than the default, ChainTrust. The security implications of this
setting should be carefully considered before using PeerOrChainTrust in production code.
-->
<authentication certificateValidationMode="PeerOrChainTrust"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
以下示例演示如何调用程序中的服务。
// Create a client.
CalculatorClient client = new CalculatorClient();
// Call the GetCallerIdentity service operation.
Console.WriteLine(client.GetCallerIdentity());
...
//Closing the client gracefully closes the connection and cleans up resources.
client.Close();
运行示例时,操作请求和响应将显示在客户端控制台窗口中。 在客户端窗口中按 Enter 关闭客户端。
CN=client.com
Add(100,15.99) = 115.99
Subtract(145,76.54) = 68.46
Multiply(9,81.25) = 731.25
Divide(22,7) = 3.14285714285714
Press <ENTER> to terminate client.
通过随附于消息安全示例的 Setup.bat 批处理文件,您可以使用相关证书配置客户端和服务器,以便运行一个需要证书安全性的托管应用程序。 批处理文件可以三种模式运行。 若要在 Visual Studio 的开发人员命令提示符下以单计算机模式运行,请键入 setup.bat;对于服务模式,请键入 setup.bat 服务;对于客户端模式,请键入 setup.bat 客户端。 跨计算机运行示例时,请使用客户端和服务器模式。 有关详细信息,请参阅本主题末尾的设置过程。 下面简要概述了批处理文件的不同部分,以便可以对其进行修改以在适当配置中运行:
创建客户端证书。
批处理文件中的以下行将创建客户端证书。 创建的证书的主题名称中会使用指定的客户端名称。 证书存储在
My
存储位置下的CurrentUser
存储区中。echo ************ echo making client cert echo ************ makecert.exe -sr CurrentUser -ss MY -a sha1 -n CN=%CLIENT_NAME% -sky exchange -pe
将客户端证书安装到服务器的受信任证书存储中。
批处理文件中的以下行将客户端证书复制到服务器的 TrustedPeople 存储中,以便服务器可以做出相关的信任或无信任决策。 为了使在 TrustedPeople 存储中安装的证书受到 Windows Communication Foundation (WCF) 服务的信任,必须将客户端证书验证模式设置为
PeerOrChainTrust
或PeerTrust
。 请参阅前面的服务配置示例,了解如何使用配置文件完成此操作。echo ************ echo copying client cert to server's LocalMachine store echo ************ certmgr.exe -add -r CurrentUser -s My -c -n %CLIENT_NAME% -r LocalMachine -s TrustedPeople
创建服务器证书。
Setup.bat 批处理文件中的以下行创建要使用的服务器证书。
echo ************ echo Server cert setup starting echo %SERVER_NAME% echo ************ echo making server cert echo ************ makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=%SERVER_NAME% -sky exchange -pe
%SERVER_NAME% 变量指定服务器名称。 证书存储在 LocalMachine 存储中。 如果使用服务参数(如 setup.bat 服务)运行 Setup.bat 批处理文件,则 %SERVER_NAME% 包含计算机的完全限定域名。 否则,它默认为 localhost。
将服务器证书安装到客户端的受信任证书存储中。
以下行将服务器证书复制到客户端的受信任人存储中。 此步骤是必需的,因为 Makecert.exe 生成的证书不受客户端系统隐式信任。 如果已有一个证书,该证书已植根于客户端受信任的根证书(例如Microsoft颁发的证书),则不需要使用服务器证书填充客户端证书存储区。
certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
授予对证书私钥的权限。
Setup.bat 文件中的以下行可以让 ASP.NET 辅助进程帐户访问 LocalMachine 存储区中存储的服务器证书。
echo ************ echo setting privileges on server certificates echo ************ for /F "delims=" %%i in ('"%ProgramFiles%\ServiceModelSampleTools\FindPrivateKey.exe" My LocalMachine -n CN^=%SERVER_NAME% -a') do set PRIVATE_KEY_FILE=%%i set WP_ACCOUNT=NT AUTHORITY\NETWORK SERVICE (ver | findstr /C:"5.1") && set WP_ACCOUNT=%COMPUTERNAME%\ASPNET echo Y|cacls.exe "%PRIVATE_KEY_FILE%" /E /G "%WP_ACCOUNT%":R iisreset
注意
如果你使用的是非美国英语版 Windows 必须编辑 Setup.bat 文件,并将“NT AUTHORITY\NETWORK SERVICE”帐户名称替换为区域等效名称。
注意
此批处理文件中使用的工具位于 C:\Program Files\Microsoft Visual Studio 8\Common7\tools 或 C:\Program Files\Microsoft SDKs\Windows\v6.0\bin 中。 其中一个目录必须位于系统路径中。 如果已安装 Visual Studio,在路径中获取此目录的最简单方法是打开 Visual Studio 开发人员命令提示符。 单击 “开始”,然后选择“所有程序”,Visual Studio 2012,工具。 此命令提示已配置相应的路径。 否则,必须手动将相应的目录添加到路径。
设置、生成和运行示例
确保已为 Windows Communication Foundation 示例 执行One-Time 安装过程。
若要生成解决方案的 C# 或 Visual Basic .NET 版本,请按照 生成 Windows Communication Foundation 示例中的说明进行操作。
在同一计算机上运行示例
使用管理员权限打开 Visual Studio 开发人员命令提示符,并从示例安装文件夹运行 Setup.bat。 这会安装运行示例所需的所有证书。
注意
Setup.bat 批处理文件旨在从 Visual Studio 的开发人员命令提示符运行。 它要求路径环境变量指向安装 SDK 的目录。 此环境变量在 Visual Studio 开发人员命令提示符(2010)中自动设置。
输入地址
http://localhost/servicemodelsamples/service.svc
,使用浏览器验证对服务的访问。从 \client\bin 启动 Client.exe。 客户端活动显示在客户端控制台应用程序中。
跨计算机运行示例
在服务计算机上创建目录。 使用 Internet Information Services (IIS) 管理工具为此目录创建名为 servicemodelsamples 的虚拟应用程序。
将服务程序文件从 \inetpub\wwwroot\servicemodelsamples 复制到服务计算机上的虚拟目录。 确保复制 \bin 子目录中的文件。 此外,将 Setup.bat、Cleanup.bat和 ImportClientCert.bat 文件复制到服务计算机。
在客户端计算机上为客户端二进制文件创建目录。
将客户端程序文件复制到客户端计算机上的客户端目录。 此外,将 Setup.bat、Cleanup.bat和 ImportServiceCert.bat 文件复制到客户端。
在服务器上,使用管理员权限在 Visual Studio 开发人员命令提示符下运行 setup.bat 服务。 如果采用 service 参数运行 setup.bat,则使用计算机的完全限定域名创建一个服务证书,并将此服务证书导出到名为 Service.cer 的文件中。
编辑 Web.config 以反映新的证书名称(在
findValue
的 < 属性中),该名称与计算机的完全限定域名相同。将Service.cer文件从服务目录复制到客户端计算机上的客户端目录。
在客户端上,使用管理员权限在 Visual Studio 开发人员命令提示符中运行 setup.bat 客户端。 使用 客户端 参数运行 setup.bat 将创建名为 client.com 的客户端证书,并将客户端证书导出到名为Client.cer的文件。
在客户端计算机上的 Client.exe.config 文件中,更改终结点的地址值以匹配服务的新地址。 通过用服务器的完全限定域名替换 localhost 来执行此操作。
将Client.cer文件从客户端目录复制到服务器上的服务目录。
在客户端上,使用管理权限在 Visual Studio 开发人员命令提示符中运行 ImportServiceCert.bat。 这会将服务证书从 Service.cer 文件导入 CurrentUser - TrustedPeople 存储中。
在服务器上,使用管理权限在 Visual Studio 的开发人员命令提示符中运行 ImportClientCert.bat。 这会将客户端证书从 Client.cer 文件导入 LocalMachine - TrustedPeople 存储。
在客户端计算机上,从命令提示符窗口启动 Client.exe。 如果客户端和服务无法通信,请参阅 WCF 示例 故障排除提示。
运行示例后进行清理
运行完示例后,在示例文件夹中运行 Cleanup.bat。
注意
在跨计算机运行此示例时,此脚本不会删除客户端上的服务证书。 如果已运行跨计算机使用证书的 Windows Communication Foundation (WCF) 示例,请确保清除已安装在 CurrentUser - TrustedPeople 存储中的服务证书。 为此,请使用以下命令:
certmgr -del -r CurrentUser -s TrustedPeople -c -n <Fully Qualified Server Machine Name>
例如:certmgr -del -r CurrentUser -s TrustedPeople -c -n server1.contoso.com
。