艾伟_转载:WCF安全之EndPointIdentity
2011-08-29 00:22
218 查看
最近在做一个项目,应用了WCF进行分布式开发,中间还涉及到消息路由器等,好在有WCF提供了强大的基础支持,当然,本身也作了不少的扩展,实际,我 最关心的是WCF的安全问题,网上不少朋友介绍的WCF的安全也是少得可怜,微软发布的WCF Security GUID好像讲得也只是入门级别的教程,离真正应用到项目中还是有很大的距离,这也让我萌发了分享的想法,今天先放出来占个位置吧,有反对的朋友砖头轻 点,呵~,可以告诉你,WCF的安全里,有很多的小秘密,当然还是要告诉你,并且有此小秘密是要自己去体验后才知道,在博客排版方面,李会军(军哥)让人 感觉最舒服,在解说方面,军哥也是以简洁著称,我在这里也学习一下,一起简洁吧,我希望以后的WCF安全探讨里,一次只讲一个小内容好了~
概述
Windows Communication Foundation (WCF) 是 Microsoft 为构建面向服务的应用程序而提供的统一编程模型(摘自MSDN),在分布式环境下的安全问题尤为重要,如果你觉得使用了WCF默认的安全措施可以让你高枕 无忧,那明天你可就以回家种田了,当然,对于学习来说,足够了~,但我们讲的是真正的项目应用,WCF在各种协议下的安全提供和保证是不尽相同的。
背景
故事发生在一个阳光明媚的下午,一名女子为了混入某小区行窃,将上次偷到的管道维修工作牌别在胸前,当她走近管理员身边时,被管理员一把抓个正着,原来这小区从上次失窃事件后,已经将维修队解散,现在维修都是由管理员联系外部人员,自然也不用别什么工作牌了。
问题呈现
1、许多朋友对这个EndPointIdentity相当的不屑顾,千万不要小看它呀,有时候你被wcf弄生弄死的时候还不知道为什么,这次你应该看清楚了。当你新建一个WCF服务类库时,正确的EndPointIdentity声明如下
看看配置文件,你发现了什么?是的,服务器端的标识被删除,客户端的标识还是dns并且值为localhost,调用服务抛出异常:
==========================
传出消息标识检查失败。所预期的远程终结点的 DNS 标识为“localhost”,但是远程终结点提供的 DNS 请求为“192168168151service”。如果此远程终结点合法,您可以通过在创建通道代理时明确地将 DNS 标识“192168168151service”指定为 EndpointAddress 的“标识”属性来解决此问题。
==========================
在这里,我们忽略了一个事实,当你在服务中将安全策略调整了消息级别安全时,服务必须配置x509证书,正所谓你叫天不应,叫地不灵啊,这时候EndpointIdentity跑出来搞乱了,明明服务器默认是dns标识,值为:loclahost。为什么突然跑出来个“192168168151service”呀?我也很想知道,原来,在服务配置证书后,默认的dns将被替换为证书主题,只要你把dns配置改回来,一切又没问题了。
[b]新问题[/b]
这时候突然冒出来一个新的问题,如果有多个服务器的时候怎么办呀?多个服务器,多半会伴随着路由器的出现(这只是一种假设,与业务有关),我也很想知道,有多个的时候的情况。
解决它
答案是通过代码动态创建一个EndpointIdentity,代码比较简单,如下:
UserDataClient client = new UserDataClient();
EndpointIdentity identity = EndpointIdentity.CreateDnsIdentity("192168168151service");
AddressHeaderCollection headers = client.Endpoint.Address.Headers;//如果需要,还可以在这里加入自定义的头消息
Uri uri = client.Endpoint.Address.Uri;
EndpointAddress remoteaddress = new EndpointAddress(uri, identity, headers.ToArray());
UserDataClient newClient = new UserDataClient(client.Endpoint.Binding, remoteaddress);
newClient.ClientCredentials.ClientCertificate.Certificate = client.ClientCredentials.ClientCertificate.Certificate;
client.Abort();//关闭旧通道,当然,这里你还可以用通道工厂创建对象,实际上也很简单
string msg = newClient.GetData(50);
===========================================================
后话
1、实际上,以上的这段代码这里还包括动态的创建地址头的相关信息,声明一个client的好处是可以使用原有的地址头信息(uri,binding等)
2、下篇更精彩,欢迎转载,但请注明出处--梁规晓博客(http://www.cnblogs.com/viter/)!
说得不对的地方,欢迎拍砖!
概述
Windows Communication Foundation (WCF) 是 Microsoft 为构建面向服务的应用程序而提供的统一编程模型(摘自MSDN),在分布式环境下的安全问题尤为重要,如果你觉得使用了WCF默认的安全措施可以让你高枕 无忧,那明天你可就以回家种田了,当然,对于学习来说,足够了~,但我们讲的是真正的项目应用,WCF在各种协议下的安全提供和保证是不尽相同的。
背景
故事发生在一个阳光明媚的下午,一名女子为了混入某小区行窃,将上次偷到的管道维修工作牌别在胸前,当她走近管理员身边时,被管理员一把抓个正着,原来这小区从上次失窃事件后,已经将维修队解散,现在维修都是由管理员联系外部人员,自然也不用别什么工作牌了。
问题呈现
1、许多朋友对这个EndPointIdentity相当的不屑顾,千万不要小看它呀,有时候你被wcf弄生弄死的时候还不知道为什么,这次你应该看清楚了。当你新建一个WCF服务类库时,正确的EndPointIdentity声明如下
//客户端配置 <binding name="EndpointBinding"> <security mode="Message"> <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign"/> <message clientCredentialType="Certificate"/> security> binding> netTcpBinding> bindings> <client> <endpoint address ="net.tcp://localhost:8799/UserService/UserData" binding="netTcpBinding" contract="Client.References.IUserData" bindingConfiguration="EndpointBinding" behaviorConfiguration="UserDataBehavior"> <identity> <dns value="localhost"/> identity> endpoint> client> //服务器配置 <binding name="EndpointBinding"> <security mode="Message"> <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign"/> <message clientCredentialType="Certificate"/> security> binding> netTcpBinding> bindings> <services> <service name="UserService.UserData" behaviorConfiguration="UserDataBehavior"> <host> <baseAddresses> <add baseAddress = "net.tcp://localhost:8799/UserService" /> baseAddresses> host> <endpoint address ="UserData" binding="netTcpBinding" contract="UserService.IUserData" bindingConfiguration="EndpointBinding"> endpoint> service>
看看配置文件,你发现了什么?是的,服务器端的标识被删除,客户端的标识还是dns并且值为localhost,调用服务抛出异常:
==========================
传出消息标识检查失败。所预期的远程终结点的 DNS 标识为“localhost”,但是远程终结点提供的 DNS 请求为“192168168151service”。如果此远程终结点合法,您可以通过在创建通道代理时明确地将 DNS 标识“192168168151service”指定为 EndpointAddress 的“标识”属性来解决此问题。
==========================
在这里,我们忽略了一个事实,当你在服务中将安全策略调整了消息级别安全时,服务必须配置x509证书,正所谓你叫天不应,叫地不灵啊,这时候EndpointIdentity跑出来搞乱了,明明服务器默认是dns标识,值为:loclahost。为什么突然跑出来个“192168168151service”呀?我也很想知道,原来,在服务配置证书后,默认的dns将被替换为证书主题,只要你把dns配置改回来,一切又没问题了。
[b]新问题[/b]
这时候突然冒出来一个新的问题,如果有多个服务器的时候怎么办呀?多个服务器,多半会伴随着路由器的出现(这只是一种假设,与业务有关),我也很想知道,有多个的时候的情况。
解决它
答案是通过代码动态创建一个EndpointIdentity,代码比较简单,如下:
UserDataClient client = new UserDataClient();
EndpointIdentity identity = EndpointIdentity.CreateDnsIdentity("192168168151service");
AddressHeaderCollection headers = client.Endpoint.Address.Headers;//如果需要,还可以在这里加入自定义的头消息
Uri uri = client.Endpoint.Address.Uri;
EndpointAddress remoteaddress = new EndpointAddress(uri, identity, headers.ToArray());
UserDataClient newClient = new UserDataClient(client.Endpoint.Binding, remoteaddress);
newClient.ClientCredentials.ClientCertificate.Certificate = client.ClientCredentials.ClientCertificate.Certificate;
client.Abort();//关闭旧通道,当然,这里你还可以用通道工厂创建对象,实际上也很简单
string msg = newClient.GetData(50);
===========================================================
后话
1、实际上,以上的这段代码这里还包括动态的创建地址头的相关信息,声明一个client的好处是可以使用原有的地址头信息(uri,binding等)
2、下篇更精彩,欢迎转载,但请注明出处--梁规晓博客(http://www.cnblogs.com/viter/)!
说得不对的地方,欢迎拍砖!
相关文章推荐
- 艾伟:WCF安全之EndPointIdentity
- WCF安全之EndPointIdentity
- WCF安全之EndPointIdentity
- 我的WCF之旅(2):Endpoint Overview(转载)
- [WCF安全系列]服务凭证(Service Credential)与服务身份(Service Identity)
- 如何配置不启用安全的WCF服务?(转载)
- 解决为WCF加强SecurityMode后引发的EndPointIdentity相关问题
- [WCF安全系列]服务凭证(Service Credential)与服务身份(Service Identity)
- WCF 异常:无法打开安全通道,因为与远程终结点的安全协商已失败。这可能是由于用于创建通道的 EndpointAddress 中不存在 EndpointIdentity ....
- 艾伟_转载:WCF、Net remoting、Web service概念及区别
- 艾伟_转载:WCF版的PetShop之三:实现分布式的Membership和上下文传递
- 艾伟_转载:WCF基本异常处理模式[上篇]
- 艾伟_转载:WCF版的PetShop之一:PetShop简介
- 艾伟_转载:WCF基本异常处理模式[下篇]
- 艾伟_转载:WCF基本异常处理模式[中篇]
- 艾伟_转载:消息队列(Message Queue)简介及其使用
- [转载]手工安全测试方法&修改建议
- 艾伟_转载:[原创]再谈IIS与ASP.NET管道
- WCF分布式开发常见错误解决(9):无终结点监听,There was no endpoint listening at
- WCF安全编程--基本概念