WCF 使用证书认证 方法
1、 打开 VS2010 Prompt 工具,创建证书。
输入以下命令:
makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=localhost -sky exchange -pe certmgr.exe -add -r LocalMachine -s My -c -n localhost -r CurrentUser -s TrustedPeople
2、设置证书访问权限
按照下面的步骤可解决 IIS7 Keyset does not exist 的问题, 根源为权限问题
1:运行 输入 mmc 2:Console -> file->add/remove snap/in 3:弹出的界面左边第三项:certificates-> add 3:弹出的界面选择computer Account 下一步第一个项 ok。 4:certificates下面找到 Personal certificates 右边 可以找到你创建的证书 5:最关键的一步:右击证书->All tasks-> manager private keys->在谈出的security中加入 everyone full control
3、创建项目
3.1 项目结构
3.2 服务端代码(service.cs)
View Code
// Copyright (c) Microsoft Corporation. All Rights Reserved. using System; using System.ServiceModel; namespace Microsoft.ServiceModel.Samples { // Define a service contract. [ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")] public interface ICalculator { [OperationContract] bool IsCallerAnonymous(); [OperationContract] double Add(double n1, double n2); [OperationContract] double Subtract(double n1, double n2); [OperationContract] double Multiply(double n1, double n2); [OperationContract] double Divide(double n1, double n2); } // Service class which implements the service contract. // Added code to return whether the caller is anonymous public class CalculatorService : ICalculator { public bool IsCallerAnonymous() { // ServiceSecurityContext.IsAnonymous returns true if the caller is not authenticated return ServiceSecurityContext.Current.IsAnonymous; } public double Add(double n1, double n2) { double result = n1 + n2; return result; } public double Subtract(double n1, double n2) { double result = n1 - n2; return result; } public double Multiply(double n1, double n2) { double result = n1 * n2; return result; } public double Divide(double n1, double n2) { double result = n1 / n2; return result; } } }
3.3 服务端(service.svc)
<%@ServiceHost language=c# Debug="true" Service="Microsoft.ServiceModel.Samples.CalculatorService" %>
3.4 客户端代码(client.cs)
View Code
// Copyright (c) Microsoft Corporation. All Rights Reserved. using System; using System.ServiceModel; namespace Microsoft.ServiceModel.Samples { //The service contract is defined in generatedClient.cs, generated from the service by the svcutil tool. //Client implementation code. class Client { static void Main() { // Create a client with given client endpoint configuration CalculatorClient client = new CalculatorClient(); // Call the GetCallerIdentity operation Console.WriteLine("IsCallerAnonymous returned: {0}", client.IsCallerAnonymous()); // Call the Add service operation. double value1 = 100.00D; double value2 = 15.99D; double result = client.Add(value1, value2); Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result); // Call the Subtract service operation. value1 = 145.00D; value2 = 76.54D; result = client.Subtract(value1, value2); Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result); // Call the Multiply service operation. value1 = 9.00D; value2 = 81.25D; result = client.Multiply(value1, value2); Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result); // Call the Divide service operation. value1 = 22.00D; value2 = 7.00D; result = client.Divide(value1, value2); Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result); //Closing the client gracefully closes the connection and cleans up resources client.Close(); Console.WriteLine(); Console.WriteLine("Press <ENTER> to terminate client."); Console.ReadLine(); } } }
3.5、 设置WCF 项目中的(服务端)配置文件
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <services> <service name="Microsoft.ServiceModel.Samples.CalculatorService" behaviorConfiguration="CalculatorServiceBehavior"> <!-- this endpoint is exposed at the base address provided by host: http://localhost/servicemodelsamples/service.svc --> <endpoint address="" binding="wsHttpBinding" bindingConfiguration="Binding1" contract="Microsoft.ServiceModel.Samples.ICalculator" /> <!-- the mex endpoint is exposed at http://localhost/servicemodelsamples/service.svc/mex --> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> <bindings> <wsHttpBinding> <!-- This configuration defines the security mode as Message and the clientCredentialType as None. This mode provides server authentication only using the service certificate. --> <binding name="Binding1"> <security mode = "Message"> <message clientCredentialType="None"/> </security> </binding> </wsHttpBinding> </bindings> <!--For debugging purposes set the includeExceptionDetailInFaults attribute to true--> <behaviors> <serviceBehaviors> <behavior name="CalculatorServiceBehavior"> <!-- The serviceCredentials behavior allows one to define a service certificate. A service certificate is used by a client to authenticate the service and provide message protection. This configuration references the "localhost" certificate installed during the setup instructions. --> <serviceCredentials> <serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" /> </serviceCredentials> <serviceMetadata httpGetEnabled="True"/> <serviceDebug includeExceptionDetailInFaults="False" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
3.6、设置客户端(App.Config)
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <client> <endpoint name="" address="http://localhost/TestService/service.svc" binding="wsHttpBinding" behaviorConfiguration="ClientCredentialsBehavior" bindingConfiguration="Binding1" contract="Microsoft.ServiceModel.Samples.ICalculator" /> </client> <bindings> <wsHttpBinding> <!-- This configuration defines the security mode as Message and the clientCredentialType as None. --> <binding name="Binding1"> <security mode = "Message"> <message clientCredentialType="None"/> </security> </binding> </wsHttpBinding> </bindings> <behaviors> <endpointBehaviors> <behavior name="ClientCredentialsBehavior"> <clientCredentials> <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> </configuration>
本示例提供代码下载