上一篇文章中介绍了如何使用wsHttpBinding构建UserName授权的WCF应用程序,本文将为您介绍如何使用wsHttpBinding构建基于SSL的UserName安全授权的WCF应用程序。

  与上篇文章一样,同样将该示例分为服务端与客户端介绍。

  1. 服务端

  (1) 实现CustomUserNameValidator

  首先实现CustomUserNameValidator,如何创建CustomUserNameValidator请参见第一篇第二篇文章。

 public class CustomUserNameValidator : UserNamePasswordValidator
{
  private const string USERNAME_ELEMENT_NAME = "userName"; private const string PASSWORD_ELEMENT_NAME = "password"; private const string FAULT_EXCEPTION_MESSAGE = "UserName or Password is incorrect!"; public override void Validate(string userName, string password)
{
  Guarder.Guard.ArgumentNotNull(userName)
.ArgumentNotNull(password);
var validateUserName = ConfigurationManager.AppSettings[USERNAME_ELEMENT_NAME];
var validatePassword = ConfigurationManager.AppSettings[PASSWORD_ELEMENT_NAME];
var validateCondition = userName.Equals(validateUserName) && password.Equals(validatePassword);
if (!validateCondition)
{
  throw new FaultException(FAULT_EXCEPTION_MESSAGE);
}
  }
}

  (2) 注册服务端证书

  与上篇文章中一样,首先需要向currentUser或localMachine中注册一个X509证书。

 makecert.exe -sr CurrentUser -ss My -a sha1 -n CN=ServerCert -sky exchange –pe

  (3) 完成服务端配置文件

 <?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<add key="username" value="username"/>
<add key="password" value="password"/>
</appSettings>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="securityBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate
findValue="ServerCert"
x509FindType="FindBySubjectName"
storeLocation="CurrentUser"
storeName="My"/>
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="TimeSynchronizeHttpsServer.CustomUserNameValidator,TimeSynchronizeHttpsServer"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="securityMessageBinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Basic"/>
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="TimeSynchronizeHttpsServer.TimeSynchronizeService" behaviorConfiguration="securityBehavior">
<endpoint address="https://127.0.0.1:12218/TimeSynchronize"
binding="wsHttpBinding" bindingConfiguration="securityMessageBinding"
contract="TimeSynchronizeHttpsServer.ITimeSynchronizeService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/Design_Time_Addresses/TimeSynchonizeHttpsServer/TimeSynchronizeService/" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>

  其中serviceCredentials节点中添加了serviceCertificate节点,该节点用来指定使用的证书。findValue,此attribute指定的是(2)中命令行中CN=右侧的字符。userNameAuthentication制定了自定义的Validator。binding节点中使用了wsHttpBinding,并将传输的加密方式指定为TransportWithMessageCredential,并制定Message的授权方式为UserName,Transport的授权方式为Basic。endpoint的地址需要使用https协议作为基地址的头部。

  (4) 将服务端应用程序绑定到SSL证书上

  如果你的WCF的承载方式为self-host(所谓self-host方式,指将WCF服务host在一个windows外壳中,包括winform、wpf、windowService。这种方式是相对于IIS承载来说的,IIS承载方式网上介绍的例子已经很多了,这篇文章主要介绍self-host方式。),需要手动将你的外壳程序绑定到SSL证书上。

  首先需要使用(2)中的方式在LocalMachine中建立一个证书,注意,一定是LocalMachine中。然后,使用下面的命令行代码,将你的服务端外壳程序绑定到SSL证书上。

 netsh http add sslcert ipport=0.0.0.0:12218 certhash=1dca86867481b22c8f15a134df62af649cc3343a clientcertnegotiation=enable appid={02639d71-0935-35e8-9d1b-9dd1a2a34627}

  其中,ipport的值中的0.0.0.0代表本地地址,冒号后面代表端口;certhash的值为证书的thumbPrint值,怎么找到这个值呢?follow this article吧,哈哈,英文的,z正好提高一下你的英语水平,哈哈。appid中的值是程序的guid,在项目属性的assemblyInfo中可以找到。

  2. 客户端

  (1) 实现CertificateValidator

  这个是在第二篇文章中没有的,这个Validator干啥用的呢。这个东西是因为我们的证书都是自己颁发给给自己的,所以在安全性上存在一些问题,如果我们用根证书颁发机构颁发的证书,让这个Validator见鬼去吧,哈哈。

 class CertificateValidator
{
  public static void SetCertificatePolicy ( )
  {
    ServicePointManager.ServerCertificateValidationCallback
+= RemoteCertificateValidate;
  }
  private static bool RemoteCertificateValidate ( object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error )
  {
    System.Console.WriteLine ( "Warning, trust any certificate" );
  return true;
  }
}

  在客户端调用代码时,调用客户端的Contract之前,调用CertificateValidator.SetCertificatePolicy()方法。

  (2) 完成客户端配置文件

 <?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<add key="username" value="username"/>
<add key="password" value="password"/>
</appSettings>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="securityMixedBinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Basic"/>
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://127.0.0.1:12218/TimeSynchronize"
binding="wsHttpBinding" bindingConfiguration="securityMixedBinding"
contract="ITimeSynchronizeService"
name="DefaultBinding_ITimeSynchronizeService_ITimeSynchronizeService" />
</client>
</system.serviceModel>
</configuration>

  需要注意的是,binding节点需要与服务端配置文件中的binding配置相同。endpoint的地址与service相同,都要采用https基地址。

  (3) 实现客户端调用代码

 private const string USERNAME = "userName";
private const string PASSWORD = "password"; static void Main ( string[] args )
{
  var proxy = new TimeSynchronizeServiceClient ( );
var userName = ConfigurationManager.AppSettings[USERNAME];
var password = ConfigurationManager.AppSettings[PASSWORD];
proxy.ClientCredentials.UserName.UserName = userName;
proxy.ClientCredentials.UserName.Password = password;
CertificateValidator.SetCertificatePolicy ( );
var time = proxy.GetTime ( );
var builder = new StringBuilder ( );
builder.Append ( "Server time is:" ).Append ( " " ).Append ( time );
var message = builder.ToString ( );
Console.WriteLine ( message );
Console.ReadKey ( );
}

  在调用客户端的Contract之前,需要调用CertificateValidator.SetCertificatePolicy()方法。

  OK,打完收工。

[WCF安全3]使用wsHttpBinding构建基于SSL与UserName授权的WCF应用程序的更多相关文章

  1. 使用wsHttpBinding构建Message安全模式和UserName授权

    http://www.cnblogs.com/artech/archive/2011/05/22/authentication_01.html https://www.cnblogs.com/Fran ...

  2. [WCF安全2]使用wsHttpBinding构建UserName授权的WCF应用程序,非SSL

    上一篇文章中介绍了如何使用basicHttpBinding构建UserName授权的WCF应用程序,本文将为您介绍如何使用wsHttpBinding构建非SSL的UserName安全授权的WCF应用程 ...

  3. [WCF安全1]使用basicHttpBinding构建UserName授权的WCF应用程序

    最近到了新公司,leader让我研究一下WCF的传输安全机制.以前也做过WCF的应用,但是很少涉及安全方面的东西.所以,花了三天的时间研究了一下如何在WCF的应用程序中配置安全.在这个系列文章中,我会 ...

  4. 基于SSL实现Mysql加密主从

    Mysql主从复制是明文传输的,对于一些特殊的场合是绝对不允许的,数据的安全性会受到威胁,在这里,简单的构建基于SSL的mysql主从复制 Ps:这里采用master-mysql为CA服务器 主端生成 ...

  5. 基于SSL实现MySQL的加密主从复制

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u012974916/article/details/53316758 大家都知道MySQL的主从复制 ...

  6. 重温WCF之WCF传输安全(十三)(2)基于SSL的WCF匿名客户端(转)

    转载地址:http://www.cnblogs.com/lxblog/archive/2012/09/13/2683514.html 这一篇我们利用上一篇制作的证书,来演示一个基于SSL的WCF服务, ...

  7. 重温WCF之WCF传输安全(十三)(4)基于SSL的WCF对客户端采用证书验证(转)

    转载地址:http://www.cnblogs.com/lxblog/archive/2012/09/20/2695397.html 前一篇我们演示了基于SSL的WCF 对客户端进行用户名和密码方式的 ...

  8. 构建基于WCF Restful Service的服务

    前言 传统的Asmx服务,由于遵循SOAP协议,所以返回内容以xml方式组织.并且客户端需要添加服务端引用才能使用(虽然看到网络上已经提供了这方面的Dynamic Proxy,但是没有这种方式简便), ...

  9. [转]构建基于WCF Restful Service的服务

    本文转自:http://www.cnblogs.com/scy251147/p/3566638.html 前言 传统的Asmx服务,由于遵循SOAP协议,所以返回内容以xml方式组织.并且客户端需要添 ...

随机推荐

  1. 通过EditText的setTransformationMethod()隐藏或显示密码

    private Button mBtnPassword; private EditText mEtPassword; private boolean mbDisplayFlg = false; /** ...

  2. ios元素定位

    原文地址http://www.cnblogs.com/meitian/p/7373460.html 第一种:通过Appium1.6的Inspector来查看 具体安装方式前面的随笔已经介绍了:http ...

  3. Cout<<XXX<<<XXX<<<XXX,是从左到右计算的

    int a=1,b=2,c=3;    cout<<(c=a+b)<<' '<<(a=b+c)<<' '<<(b=a+c)<<e ...

  4. JavaScript:传对象数组到后台

    页面: <script> function improve() { var improveForm = $('#improveForm'); if (!improveForm.valid( ...

  5. html-4, form 表单 输入、传文件、单选、多选、下拉菜单、文本描述、重置、submit、按钮限制输入

    <!-- form HTTP协议 action:提交的服务器网址 method:get(默认)| post(应用:登录注册.上传文件) 页面中的a img link 默认是get请求 input ...

  6. Visual studio插件 Reshaper--- 常用快捷键

    快速修复 alt+enter (alt+enter唤出快速修复面板,上下方向键进行选择,再次敲击enter键确定修改) 跳转到对象声明 ctl+鼠标左键 重构-重命名(ctl+r+r) esc键退出 ...

  7. cocosBuider 控件命名的坑

    这几天遇到了各种坑.... 各种控件名字问题.... bool CLevelLayer::onAssignCCBMemberVariable(cocos2d::CCObject * pTarget, ...

  8. 修改myeclipse字体与操作系统的字体一致

    如果你是win7系统,想要修改Myeclipse字体,步骤如下:第一步:C:\Windows\Fonts,找到Courier New,鼠标右键-->显示第二步:Ceneral --> Ap ...

  9. 微服务-使用Redis实现分布式缓存

    在单体中对于key信息和用户信息是放在内存中放的,通过session进行管理. 微服务是要放在分布式缓存中,以实现服务的无状态化. @Autowired private StringRedisTemp ...

  10. Spring事务回滚

    配置事物: @Configuration /**强制使用cglib代理时就把proxy-target-class设为true.*/ @EnableTransactionManagement(proxy ...