11 安全

前言

  【1】传输安全
     传输安全模式
     传输安全与绑定协议
 
  【2】身份验证
     身份验证分类
     证书
     示例:传输安全匿名客户端证书的使用

1. 传输安全

     保证信息在传输过程中的安全.传输安全是身份验证和授权的前提。

  传输安全模式

    None:关闭了传输安全的功能
    transport security:对通道上所有的通信加密,除了接收者外,没有任何一方可以看见消息的内容。
    message security:只是对消息的本身进行加密而不是对传输进行加密。
    Mixed:在实现完整性和机密性以及服务端身份验证时采用的是Transport Security模式,而在保护客户端安全凭证的安全时采用了Message Security模式。
    Both:同是使用Transport模式和Message模式,就是传输时安全的,传输的消息也是经过加密的.

配置

    传输安全模式是在绑定中配置的.

  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 传输安全必须要使用证书

    SSL安全套接字层是一个数据传输加密机制,它可以确保在客户机与服务器之间传输的数据仍然是安全与隐密的。
    传输安全 (HTTPS) 确保保密性和完整性。
    SSL 广泛用于 Internet 中,以便向客户端证明服务的身份,并且随后向通道提供保密性(加密)。
    证书就相当于是身份证一样,客户端可以不进行身份验证。但是要有一个服务器证书来保证客户端和服务器之间能够建立SSL安全套接字连接。
 

3.2 证书制作

    【1】使用Makecert命令创建证书
      Makecert证书创建工具生成的 X.509 证书。
    它创建用于数字签名的公钥和私钥对,并将其存储在证书文件中。
    此工具还将密钥对与指定发行者的名称相关联,并创建一个 X.509 证书,该证书将用户指定的名称绑定到密钥对的公共部分。

    步骤:

    第一步:创建证书

      打开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客户端凭证类型)

    1.None
    2.Basic
    3.Digest
    4.HTLM
    5.Windows
    6.Certificate
    

<bindings>
<netTcpBinding>
<binding name="">
<security mode="Transport">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</netTcpBinding>
</bindings>

  【2】身份验证类型(Message客户端凭证类型)

    1.None
    2.Windows
    3.Username
    4.Certificate
    5.Windows CardSpace

  

 <bindings>
<wsHttpBinding>
<binding name="">
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>

5.1 示例:Basic身份验证

    传输安全模式之基本身份验证:

  传输安全模式之基本身份验证需要服务器需要一个有效的可用于安全套接字层 (SSL) 的 X.509 证书,

  并且客户端必须信任此服务器证书。如果不信任此证书会导致建立SSL传输连接失败,因为客户端会认为服务端是一个非法的服务端,因而建立SSL安全套接层失败。

    1.身份验证(服务器):提供证书,(使用 HTTPS)
    2.身份验证(客户端):提供用户名/密码

    客户端建立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】

【WCF--初入江湖】11 安全的更多相关文章

  1. [WCF编程]11.错误:错误契约

    一.错误传播 服务需要向客户端报告特定错误,当WCF默认的错误屏蔽方法并不包含这一实现.另一个重要的问题与传播到客户端有关,即由于异常是针对特定技术的,因此无法跨越服务边界而被共享.要实现无缝的互操作 ...

  2. [WCF编程]11.错误:错误类型

    一.错误概述 不管是哪一种操作,在任意时刻都可能出现不可预期的错误.问题在于我们应该如何将错误报告给客户端.异常和异常处理机制是与特定技术紧密结合的,不能跨越边界的.此外,如果有客户端来处理错误,必定 ...

  3. WCF初探-11:WCF客户端异步调用服务

    前言: 在上一篇WCF初探-10:WCF客户端调用服务 中,我详细介绍了WCF客户端调用服务的方法,但是,这些操作都是同步进行的.有时我们需要长时间处理应用程序并得到返回结果,但又不想影响程序后面代码 ...

  4. 传说中的WCF(11):会话(Session)

    在标题中我加了一个大家都很熟悉的单词——Session,熟吧?玩过Web开发的朋友肯定在梦中都会见到她. 在Web中为什么要会话呢?毕竟每个用户在一个Web应用中可能不止进行一次操作,比如,某二手飞机 ...

  5. WCF初探文章列表

    WCF初探-1:认识WCF WCF初探-6:WCF服务配置 WCF初探-2:手动实现WCF程序 WCF初探-7:WCF服务配置工具使用 WCF初探-3:WCF消息交换模式之单向模式 WCF初探-8:W ...

  6. WCF初探-15:WCF操作协定

    前言: 在前面的文章中,我们定义服务协定时,在它的操作方法上都会加上OperationContract特性,此特性属于OperationContractAttribute 类,将OperationCo ...

  7. WCF身份验证二:基于消息安全模式的自定义身份验证

    使用X509证书进行身份验证应该说是WCF安全模型中最”正常”的做法, 因为WCF强制要求使用证书加密身份数据, 离开了证书, 所有的身份验证机制拒绝工作, WCF支持的身份验证机制也相当复杂, 这里 ...

  8. 地区sql

    /*Navicat MySQL Data Transfer Source Server : localhostSource Server Version : 50136Source Host : lo ...

  9. WCF入门(11)

    前言 终于出太阳了. 可惜风太大,凉在阳台上的衣服全被吹到了地上,外加几双袜子被吹掉了,gone. 第11集 Difference between DataContract and MessageCo ...

  10. 跟我一起学WCF(11)——WCF中队列服务详解

    一.引言 在前面的WCF服务中,它都要求服务与客户端两端都必须启动并且运行,从而实现彼此间的交互.然而,还有相当多的情况希望一个面向服务的应用中拥有离线交互的能力.WCF通过服务队列的方法来支持客户端 ...

随机推荐

  1. CentOS 7.2 无法生成 coredump文件

    CentOS版本 cat /etc/centos-release  CentOS Linux release 7.2.1511 (Core) 设置ulimit -c ulimited 依旧无法生成co ...

  2. 在Java中怎样把数组转换为ArrayList?

    翻译自:How to Convert Array to ArrayList in Java? 本文分析了Stack Overflow上最热门的的一个问题的答案,提问者获得了很多声望点,使得他得到了在S ...

  3. js实现模拟自动点击按钮,并且在10秒倒计时之后疯狂点击

    需求来自于csdn问答,可以利用这个原理做秒杀抢单外挂. 代码示例如下: <html> <head> <meta charset="utf-8"/&g ...

  4. SequoiaDB数据库的一般概念介绍

    SequoiaDB数据库的主要对象包括文档.集合.集合空间与索引等. 文档 SequoiaDB中的文档为JSON格式,一般又被称为记录.在数据库内部使用BSON,即二进制的方式存放JSON数据.一般情 ...

  5. cookie工作原理

    当客户访问某个基于PHP技术的网站时,在PHP中可以使用setcookie()函数生成一个cookie,系统经处理把这个cookie发送到客户端并保存在C:\Documents andSettings ...

  6. php威盾解密的例子分享

    例子,批量解密  代码如下 复制代码 <?php/************************************威盾PHP加密专家解密算法 By:zhrt*http://www.111 ...

  7. Apache,添加虚拟目录

    这几天在自己的虚拟机里面安装了2003,有人说window陪iis较好,但是对iis无兴趣,就自己装了apache,下面介绍如何配置自己的虚拟目录. 想配置自己的虚拟目录,那必须要知道点apache的 ...

  8. 左右滑动删除ListView条目Item--第三方开源--SwipeToDismiss

    Android的SwipeToDismiss是github上一个第三方开源框架(github上的项目链接地址:https://github.com/romannurik/Android-SwipeTo ...

  9. Oracle表空间、段、区和块

    数据块(Block) 数据块Block是Oracle存储数据信息的最小单位.注意,这里说的是Oracle环境下的最小单位.Oracle也就是通过数据块来屏蔽不同操作系统存储结构的差异.无论是Windo ...

  10. IE6和IE7的line-height和现代浏览器不一致的问题

    1.我们发现在网页中设置line-height后,现代浏览器显示正常,可是在IE6 IE7下却不能正确解析,这时需要再额外的为旧版浏览器声明: p{ line-height: 30px; *line- ...