11 安全
前言
1. 传输安全
传输安全模式:
配置
传输安全模式是在绑定中配置的.
binding与传输安全模式
传输安全模式与各种binding是一个组合的关系,并不是每种binding都能应用所有的传输安全模式,
所有WCF的绑定默认都是安全的,只有BasicHttpBinding默认是非安全的
名称 |
None |
Transport |
Message |
Mixed |
Both |
BasicHttpBinding |
Yes(默认) |
Yes |
Yes |
Yes |
No |
NetTcpBinding |
Yes |
Yes(默认) |
Yes |
Yes |
No |
NetNamedPipeBinding |
Yes |
Yes(默认) |
No |
No |
No |
WSHttpBinding |
Yes |
Yes |
Yes(默认) |
Yes |
No |
WSDualHttpBinding |
Yes |
No |
Yes(默认) |
No |
No |
NetMsmqBinding |
Yes |
Yes(默认) |
Yes |
No |
Yes |
配置文件的形式:
<bindings>
<netTcpBinding>
<binding name="tcpBinding">
<security mode="Transport">
<transport clientCredentialType="Windows“
protectionLevel="EncryptAndSign"/>
</security>
</binding>
</netTcpBinding>
</bindings>
编程方式实现:
NetTcpBinding binding = new NetTcpBinding(SecurityMode.Transport);
或者
NetTcpBinding binding1 = new NetTcpBinding();
binding1.Security.Mode = SecurityMode.Transport;
2. 身份验证
2.1 Transport模式的身份验证
在Transport模式下,身份验证与binding的关系
名称 |
None |
Windows |
UserName |
Certificate |
BasicHttpBinding |
Yes(默认) |
Yes |
Yes |
Yes |
NetTcpBinding |
Yes |
Yes(默认) |
No |
Yes |
NetNamedPipeBinding |
No |
Yes(默认) |
No |
No |
WSHttpBinding |
Yes |
Yes(默认) |
Yes |
Yes |
WSDualHttpBinding |
||||
NetMsmqBinding |
Yes |
Yes(默认) |
No |
Yes |
所有的局域网绑定都支持Windows方式的身份验证
NetTcpBinding在Transport模式下不支持UserName身份验证模式
wsDualHttpBinding不支持Transport传输安全模式的
2.2 Message模式的身份验证
在Message传输安全模式下Binding与身份验证
名称 |
None |
Windows |
UserName |
Certificate |
IssuedToken |
BasicHttpBinding |
No |
No |
No |
Yes |
No |
NetTcpBinding |
Yes |
Yes(默认) |
Yes |
Yes |
Yes |
NetNamedPipeBinding |
|||||
WSHttpBinding |
Yes |
Yes(默认) |
Yes |
Yes |
Yes |
WSDualHttpBinding |
Yes |
Yes(默认) |
Yes |
Yes |
Yes |
NetMsmqBinding |
Yes |
Yes(默认) |
Yes |
Yes |
Yes |
除了BasicHttpBinding和NetNamedPipeBinding以外,其他的模式默认都是用Windows凭证
示例:
<?xml version="1.0" encoding="utf-8" ?>
<configuration> <system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding_Security">
<security mode="Transport">
<transport clientCredentialType="None"/><!--启用传输安全,身份认证是匿名的-->
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="Keasy5.WCF.Security.Translation.Service1">
<host>
<baseAddresses>
<!--Http和SSL 两者要成对-->
<add baseAddress = "http://localhost:8733/Design_Time_Addresses/Keasy5.WCF.Security.Translation/Security/" />
<add baseAddress = "https://localhost:8833/Design_Time_Addresses/Keasy5.WCF.Security.Translation/Security/" />
</baseAddresses>
</host>
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="wsHttpBinding_Security"
contract="Keasy5.WCF.Security.Translation.IService1">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel> </configuration>
其中:
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding_Security">
<security mode="Transport">
<transport clientCredentialType="None"/><!--启用传输安全,身份认证是匿名的-->
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="Keasy5.WCF.Security.Translation.Service1">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8733/Design_Time_Addresses/Keasy5.WCF.Security.Translation/Security/" />
<add baseAddress = "https://localhost:8833/Design_Time_Addresses/Keasy5.WCF.Security.Translation/Security/" />
</baseAddresses>
</host>
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="wsHttpBinding_Security"
contract="Keasy5.WCF.Security.Translation.IService1">
注意:如果启用了传输安全,即:<security mode="Transport">,那么就必须提供:https开头的基地址
:
<add baseAddress = "http://localhost:8733/Design_Time_Addresses/Keasy5.WCF.Security.Translation/Security/" />
<add baseAddress = "https://localhost:8833/Design_Time_Addresses/Keasy5.WCF.Security.Translation/Security/" />
否则WCF服务抛出异常:
下面是我们注释掉:https:基地址后,
<baseAddresses>
<add baseAddress = "http://localhost:8733/Design_Time_Addresses/Keasy5.WCF.Security.Translation/Security/" />
<!--<add baseAddress = "https://localhost:8833/Design_Time_Addresses/Keasy5.WCF.Security.Translation/Security/" />-->
</baseAddresses>
抛出异常
System.InvalidOperationException: 找不到具有绑定 WSHttpBinding 的终结点的与方案 https 匹配的基址。注册的基址方案是 [http]。
设置完上述的配置后,客户端(这里使用VS对WCF服务库内置的【WCF测试客户端】)调用时发生异常:
对 https://localhost:8833/Design_Time_Addresses/Keasy5.WCF.Security.Translation/Security/ 执行 HTTP 请求时发生错误。这可能是由于在使用 HTTPS 的情况下未使用 HTTP.SYS 正确配置服务器证书造成的。这还可能是由于客户端和服务器之间的安全绑定不匹配所致。
这是因为配置中,我们启用了传输安全,但没有提供证书。
<security mode="Transport">
启用了传输安全,就必须使用证书。如何提供证书,请看下一节:3. 证书与传输安全。
3. 证书与传输安全
3.1 传输安全必须要使用证书
3.2 证书制作
步骤:
第一步:创建证书
打开Vs的【VS2013 开发人员命令提示】,输入如下命令
makecert -sr localmachine -ss My -n CN=WCFServerPK -sky exchange -pe -r
其中,
-sr localmachine -sr指定证书的存放位置,localmachine 指是存储在本机上 ,也可以是current,存放到当前用户
-ss My -ss指定证书存储的目录,My指【个人】这个目录,如果用【Hello】,则创建一个【Hello】目录
-n CN=WCFServerPK -n 指定证书的名称,cn=前缀(Common Name),WCFServerPK 是证书的名称
第二步:查看证书
打开【命令】(或者Win+R),输入mmc,确定
再选【计算机账户(C)】选项,添加控制台节点。
第三步:导出证书:
右键证书--所有任务--导出,在导出过程中有一步是要求输入密码(这里设置为123456),然后输入证书的名称WCFServicePK,最后导出
WCFServicePK.pfx文件。
第四步:在客户端上安装证书。
在客户端所在的计算机上,安装在第一步中打开的【控制台】,在【证书(本地计算机)】--【受信任人】--【证书】右键--【所有任务】--
【导入】,把第三步导出的证书导入,下面的过程证有一步要求输入证书密码(改密码就是第三步设置的证书密码123456)。
也可以为其他地方(如:受信任的根证书颁发机构)导入证书WCFServicePK.pfx。
第五步:设置SSL证书
需要一个工具:httpcfg.下载地址:
链接: http://pan.baidu.com/s/1c04DMSg 密码: me2p
下载该工具后,把它解压并保存到一个目录下,本例使用:D:/
打开命名(win+R),输入cmd,切换到D:目录
查看SSL配置:
httpcfg query ssl
设置SSL配置:
在第二步中打开的【控制台】界面的右边列表中,选择WCFServicePK,双击打开证书(或者右键--打开),在弹出框中,
选择【详细信息】--选择【指纹】,复制这些字符串,本例中这些字符串为:
832420b5499bf8eca2c924e63fb9b6192201d034
然后在输入如下命令:
httpcfg set ssl -i 0.0.0.0:8833 -h 832420b5499bf8eca2c924e63fb9b6192201d034
这样,使得证书和端口8833进行关联,其中:
【1】832420b5499bf8eca2c924e63fb9b6192201d034 就是证书的指纹。
【2】0.0.0.0:8833 8833是端口,这就是配置WCF服务时指定的Https基地址的端口
<add baseAddress = "https://localhost:8833/Design_Time_Addresses/Keasy5.WCF.Security.Translation/Security/" />
如果要删除SSL配置,可以输入:
httpcfg delete ssl -i 0.0.0.0: -h 832420b5499bf8eca2c924e63fb9b6192201d034
第六步:服务端配置证书:
<services>
<service
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" /> <serviceCredentials>
<serviceCertificate storeLocation="LocalMachine"
x509FindType="FindBySubjectName"
findValue="WCFServerPK"
storeName="My"/>
</serviceCredentials> </behavior>
</serviceBehaviors>
</behaviors>
其中,findValue的值是:3.2 第一步中 “-n CN=WCFServerPK"中指定的值
这里新建一个控制台程序作为宿主:
宿主的配置app.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration> <system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding_Security">
<security mode="Transport">
<transport clientCredentialType="None"/><!--启用传输安全,身份认证是匿名的-->
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="Keasy5.WCF.Security.Translation.Service1">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8733/Keasy5.WCF.Security.Translation/Security/" />
<add baseAddress = "https://localhost:8833/Keasy5.WCF.Security.Translation/Security/" />
</baseAddresses>
</host>
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="wsHttpBinding_Security"
contract="Keasy5.WCF.Security.Translation.IService1">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" /> <serviceCredentials>
<serviceCertificate storeLocation="LocalMachine"
x509FindType="FindBySubjectName"
findValue="WCFServerPK"
storeName="My"/>
</serviceCredentials> </behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel> </configuration>
宿主代码:
namespace Keasy5.WCF.Security.Translation.Host
{
class Program
{
static void Main(string[] args)
{
using (ServiceHost serviceHost = new ServiceHost(typeof(Service1)))
{
serviceHost.Open();
Console.WriteLine("服务已启动");
Console.ReadKey();
}
}
}
}
第七步:客户端调用服务:
新建一个控制台项目,然后引用服务,输入如下地址:
https://localhost:8833/Keasy5.WCF.Security.Translation/Security/
然后点击【转到】,这时候,弹出一个对话框【安全报警,说明SSL证书配置成功。
客户端自动生成的app.cong配置:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService1">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://localhost:8833/Keasy5.WCF.Security.Translation/Security/"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1"
contract="ServiceReference1.IService1" name="WSHttpBinding_IService1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
调用服务方法:
namespace Keasy5.WCF.Security.Translation.Client
{
class Program
{
static void Main(string[] args)
{
Service1Client service1Client = new Service1Client(); try
{
string message = service1Client.GetData("Https传输安全");
Console.WriteLine(message);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
} Console.ReadKey(); }
}
}
先启动宿主,后启动客户端;
这时,客户端抛出如下异常:
无法为 SSL/TLS 安全通道与颁发机构“localhost:”建立信任关系。
客户端调用还需要添加代码,强制信任证书:
namespace Keasy5.WCF.Security.Translation.Client
{
class Program
{
static void Main(string[] args)
{
Service1Client service1Client = new Service1Client(); //强制信任证书
ServicePointManager.ServerCertificateValidationCallback +=ServerCertificateValidationCallback;
try
{
string message = service1Client.GetData("Https传输安全");
Console.WriteLine(message);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
} Console.ReadKey(); } private static bool ServerCertificateValidationCallback(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
return true;
}
}
}
源码下载:
链接: http://pan.baidu.com/s/1eQh9iq2 密码: 4ogd
案例总结
WSHttpBinding 绑定,匿名客户端(none)的传输安全模式(Transport)
1、制作证书
2、SSL证书设置
3、服务端配置
4、客户端配置
5. 身份认证
【1】身份验证类型(transport客户端凭证类型)
<bindings>
<netTcpBinding>
<binding name="">
<security mode="Transport">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</netTcpBinding>
</bindings>
【2】身份验证类型(Message客户端凭证类型)
<bindings>
<wsHttpBinding>
<binding name="">
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
5.1 示例:Basic身份验证
传输安全模式之基本身份验证需要服务器需要一个有效的可用于安全套接字层 (SSL) 的 X.509 证书,
并且客户端必须信任此服务器证书。如果不信任此证书会导致建立SSL传输连接失败,因为客户端会认为服务端是一个非法的服务端,因而建立SSL安全套接层失败。
客户端建立SSL安全套接层以后,会使用协定的密码对消息签名,客户端使用证书加密数据,服务端使用证书解密数据,保证数据的安全和机密性。
步骤:
1、制作证书
2、SSL证书设置
3、服务端配置
传输模式设置
证书使用
4、客户端配置(用户名和密码)
第一步--第二步:与上一节相同。
第三步:服务端的配置:
<?xml version="1.0" encoding="utf-8" ?>
<configuration> <system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding_Transport">
<security mode="Transport">
<transport clientCredentialType="Basic"/><!--Basics是用户名和密码的身份认证模式-->
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="Keasy5.WCF.Credential.Service.Service1">
<host>
<baseAddresses>
<add baseAddress = "https://localhost:8833/Keasy5.WCF.Credential.Service/Service1/" />
</baseAddresses>
</host>
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="wsHttpBinding_Transport"
contract="Keasy5.WCF.Credential.Service.IService1">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
<serviceCredentials>
<serviceCertificate storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName"
findValue="WCFServerPK"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel> </configuration>
第四步:客户端调用服务
新建客户端控制台项目,添加服务引用,输入如下地址:
https://localhost:8833/Keasy5.WCF.Credential.Service/Service1/
点击【转到】,弹出一个对话框,要求你输入账户和密码:
输入服务器主机的密码后,成功添加服务器引用。
app.config文件自动添加WCF客户端配置:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService1">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://localhost:8833/Keasy5.WCF.Credential.Service/Service1/"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1"
contract="ServiceReference1.IService1" name="WSHttpBinding_IService1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
添加客户端调用代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using Keasy5.WCF.Credential.Client.ServiceReference1; namespace Keasy5.WCF.Credential.Client
{
class Program
{
static void Main(string[] args)
{
try
{
ServiceReference1.Service1Client service1 = new Service1Client();
ServicePointManager.ServerCertificateValidationCallback += ServerCertificateValidationCallback; string message = service1.GetData(); Console.WriteLine(message); }
catch (Exception e)
{
Console.WriteLine(e.Message);
} Console.ReadKey();
} private static bool ServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true; //强制信任证书
}
}
}
如果没有添加如下代码,提供服务器端主机的用户名和密码:
//使用用户名和密码进行登录服务器
service1.ClientCredentials.UserName.UserName = "easy5";
service1.ClientCredentials.UserName.Password = " ";
就会抛出异常:
未提供用户名。请在 ClientCredential 中指定用户名。
更正客户端代码:
namespace Keasy5.WCF.Credential.Client
{
class Program
{
static void Main(string[] args)
{
try
{
ServiceReference1.Service1Client service1 = new Service1Client(); //强制信任证书
ServicePointManager.ServerCertificateValidationCallback += ServerCertificateValidationCallback; //使用用户名和密码进行登录服务器
service1.ClientCredentials.UserName.UserName = "easy5";
service1.ClientCredentials.UserName.Password = " "; string message = service1.GetData(200); Console.WriteLine(message); }
catch (Exception e)
{
Console.WriteLine(e.Message);
} Console.ReadKey();
} private static bool ServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true; //强制信任证书
}
}
}
本节源码下载:
链接: http://pan.baidu.com/s/1hqtauMw 密码: eh0d
5.2 示例:Basic身份验证之自定义身份验证
5.1 示例:Basic身份验证 中的身份验证需要客户端知道服务器端的密码,显然这很不合理,
所以自定义一种验证方式。
【1】自定义身份验证配置如下:
<serviceCredentials>
。。。。。。
<clientCertificate>
<authentication certificateValidationMode="None"/>
</clientCertificate>
<userNameAuthentication userNamePasswordValidationMode=“Custom”
customUserNamePasswordValidatorType=“命名空间名.自定义验证类名,程序集名"/>
</serviceCredentials>
注意:
customUserNamePasswordValidatorType=“命名空间名.自定义验证类名, 程序集名"
必须是:命名空间名.自定义验证类名, 程序集名
否则抛出异常:
未能从程序集“System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”中
加载类型“Keasy5.WCF.Credential.Service.MyCustomUserNamePasswordValidator”。":"Keasy5.WCF.Credential.Service.MyCustomUserNamePasswordValidator"}
【2】自定义验证类
class CustomValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (userName != "xxx" || password != "xxx123")
{
Console.WriteLine("用户名或密码出错!");
throw new FaultException("用户名或密码出错!");
}
}
实现步骤:
在5.1 示例:Basic身份验证示例的基础上进行修改
第一步:在WCF服务项目:
添加System.IdentityModel程序集的引用,
添加一个j继承自UserNamePasswordValidator的类MyCustomUserNamePasswordValidator:
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.IdentityModel;
using System.IdentityModel.Tokens;
using System.IdentityModel.Selectors; namespace Keasy5.WCF.Credential.Service
{
public class MyCustomUserNamePasswordValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
//模拟数据库中的账号和密码
if (userName.ToLower().Trim() != "admin"
&& password.ToLower().Trim() != "admin")
{
throw new FaultException("用户名或密码错误");
}
}
}
}
第二步:在服务的配置文件app.config中的<serviceCredentials>节点下添加:
<!--添加自定义身份验证-->
<clientCertificate>
<authentication certificateValidationMode="None"/>
</clientCertificate>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="Keasy5.WCF.Credential.Service.MyCustomUserNamePasswordValidator
,Keasy5.WCF.Credential.Service"/>
最终的服务端配置文件为:
<?xml version="1.0" encoding="utf-8" ?>
<configuration> <system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding_Transport">
<security mode="Transport">
<transport clientCredentialType="Basic"/><!--Basics是用户名和密码的身份认证模式-->
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="Keasy5.WCF.Credential.Service.Service1">
<host>
<baseAddresses>
<add baseAddress = "https://localhost:8833/Keasy5.WCF.Credential.Service/Service1/"/>
</baseAddresses>
</host>
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="wsHttpBinding_Transport"
contract="Keasy5.WCF.Credential.Service.IService1">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
<serviceCredentials>
<serviceCertificate storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName"
findValue="WCFServerPK"/> <!--添加自定义身份验证-->
<clientCertificate>
<authentication certificateValidationMode="None"/>
</clientCertificate>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="Keasy5.WCF.Credential.Service.MyCustomUserNamePasswordValidator,Keasy5.WCF.Credential.Service"/> </serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel> </configuration>
服务宿主:
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using Keasy5.WCF.Credential.Service; namespace Keasy5.WCF.Credential.Host
{
class Program
{
static void Main(string[] args)
{
try
{
using (ServiceHost serviceHost = new ServiceHost(typeof(Service1)))
{
serviceHost.Open();
Console.WriteLine("服务已经启动,按任意键关闭服务!");
Console.ReadKey();
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.ReadKey();
} Console.ReadKey();
}
}
}
第三步:客户端引用服务:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using Keasy5.WCF.Credential.Client.ServiceReference1; namespace Keasy5.WCF.Credential.Client
{
class Program
{
static void Main(string[] args)
{
try
{
ServiceReference1.Service1Client service1 = new Service1Client("WSHttpBinding_IService1"); //强制信任证书
ServicePointManager.ServerCertificateValidationCallback +=
ServerCertificateValidationCallback; //使用用户名和密码进行登录服务器
service1.ClientCredentials.UserName.UserName = "admin";
service1.ClientCredentials.UserName.Password = "admin"; string message = service1.GetData(); Console.WriteLine(message); }
catch (Exception e)
{
Console.WriteLine(e.Message);
} Console.ReadKey();
} private static bool ServerCertificateValidationCallback(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
return true; //强制信任证书
}
}
}
客户端的配置app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService1">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://localhost:8833/Keasy5.WCF.Credential.Service/Service1/"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1"
contract="ServiceReference1.IService1"
name="WSHttpBinding_IService1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
本节源码下载:
链接: http://pan.baidu.com/s/18fG9g 密码: 5t2g
【The End】