[WCF安全3]使用wsHttpBinding构建基于SSL与UserName授权的WCF应用程序
上一篇文章中介绍了如何使用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应用程序的更多相关文章
- 使用wsHttpBinding构建Message安全模式和UserName授权
http://www.cnblogs.com/artech/archive/2011/05/22/authentication_01.html https://www.cnblogs.com/Fran ...
- [WCF安全2]使用wsHttpBinding构建UserName授权的WCF应用程序,非SSL
上一篇文章中介绍了如何使用basicHttpBinding构建UserName授权的WCF应用程序,本文将为您介绍如何使用wsHttpBinding构建非SSL的UserName安全授权的WCF应用程 ...
- [WCF安全1]使用basicHttpBinding构建UserName授权的WCF应用程序
最近到了新公司,leader让我研究一下WCF的传输安全机制.以前也做过WCF的应用,但是很少涉及安全方面的东西.所以,花了三天的时间研究了一下如何在WCF的应用程序中配置安全.在这个系列文章中,我会 ...
- 基于SSL实现Mysql加密主从
Mysql主从复制是明文传输的,对于一些特殊的场合是绝对不允许的,数据的安全性会受到威胁,在这里,简单的构建基于SSL的mysql主从复制 Ps:这里采用master-mysql为CA服务器 主端生成 ...
- 基于SSL实现MySQL的加密主从复制
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u012974916/article/details/53316758 大家都知道MySQL的主从复制 ...
- 重温WCF之WCF传输安全(十三)(2)基于SSL的WCF匿名客户端(转)
转载地址:http://www.cnblogs.com/lxblog/archive/2012/09/13/2683514.html 这一篇我们利用上一篇制作的证书,来演示一个基于SSL的WCF服务, ...
- 重温WCF之WCF传输安全(十三)(4)基于SSL的WCF对客户端采用证书验证(转)
转载地址:http://www.cnblogs.com/lxblog/archive/2012/09/20/2695397.html 前一篇我们演示了基于SSL的WCF 对客户端进行用户名和密码方式的 ...
- 构建基于WCF Restful Service的服务
前言 传统的Asmx服务,由于遵循SOAP协议,所以返回内容以xml方式组织.并且客户端需要添加服务端引用才能使用(虽然看到网络上已经提供了这方面的Dynamic Proxy,但是没有这种方式简便), ...
- [转]构建基于WCF Restful Service的服务
本文转自:http://www.cnblogs.com/scy251147/p/3566638.html 前言 传统的Asmx服务,由于遵循SOAP协议,所以返回内容以xml方式组织.并且客户端需要添 ...
随机推荐
- react 获取input标签的输入值
参考:https://segmentfault.com/a/1190000012404114 两种方法,受控组件和非受控组件. 推荐使用受控组件,即通过this.state获取,因为其符合react规 ...
- 一种部署 Python 代码的新方法
在Nylas,我们喜欢使用Python进行开发.它的语法简单并富有表现力,拥有大量可用的开源模块和框架,而且这个社区既受欢迎又有多样性.我们的后台是纯用 Python 写的,团队也经常在 PyCon ...
- CS224n(一)
个人博客地址: https://yifdu.github.io/2018/10/30/CS224n%E7%AC%94%E8%AE%B0%EF%BC%88%E4%B8%80%EF%BC%89/#more
- Spark的Driver节点和Executor节点
转载自:http://blog.sina.com.cn/s/blog_15fc03d810102wto0.html 1.驱动器节点(Driver) Spark的驱动器是执行开发程序中的 main方法的 ...
- 已经安装好了的lamp或者lnmp环境,编译其他的模块进来?
问题: 如何为已经编译好了的环境再次编译其他的模块? 方法: 一般分为两种情况: 1. php的源码安装包中本来就有这个 .so 的扩展,我们只需要进入到php的安装源码包中的ext文件夹下,然后找到 ...
- Java 面试总结 面试常问的关键字总结
文章出处http://www.cnblogs.com/IUbanana/p/7116520.html 关键字: final finalize finally throws和throw static关键 ...
- Web 框架 Flask
Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后 ...
- PKU 3318 Matrix Multiplication(神奇的输入)
#include<cstdio> using namespace std; ][]; ][],C[][]; int Read() { ; ; while((ch=getchar())==' ...
- JForum的运行环境
JForum的运行环境: 开始本文之前,我们确认一下JForum的运行环境. - Java动态运行环境(JRE) - 支持J2EE Servlet标准的任何一款Web服务器:Tomcat,JBoss, ...
- PL/SQL编程—函数
SQL> select * from mytest; ID NAME PASSWD SALARY ----- -------------------- -------------------- ...