WCF4.0进阶系列--第五章 在因特网环境下保护WCF服务
【摘要】
实现企业内部的WCF服务和客户端程序的安全需要相当的力气,但是WCF提供了绑定和行为来简化保护通信。使用.NET Framework4.0提供的认证和授权,可以确保服务和客户端消息传输的保密性,而且还确保只有经过授权的用户才能对服务提交请求。企业内部的网络环境由于内在的保密性,对比因特网其相对比较稳定;虽然也有黑客入侵,但这也只是偶尔的现象。只要系统管理员和网络管理员维护好企业基础架构的安全,那么你就基本可以信任客户端程序和服务。消息加密、用户验证、用户授权,它们都能比较容易地在企业内部部署。
但是,当客户端程序和WCF服务跨越公共网络(比如因特网)时,你便不能再假定客户端程序,WCF服务,及两者之间的通信是可以信任的。比如,客户端程序如何验证它所发送消息的服务端是否是真实的服务端,而不是替代了真实服务的冒牌服务端; 或者在消息被传送至真实服务之前冒牌服务端是否破译并记录消息;亦或服务如何区分运行客户端的用户是否就是他所声称的身份;以及服务如何分辨请求是否来自授权的客户端而不是来自一个由黑客伪装的客户端。
因特网是一个充满潜在危险的环境,因此你必须高度怀疑所有通过因特网传输的信息。在本章,你将了解如何使用一些技术来保护客户端程序,WCF服务,以及两者之间传输的信息。
【正文】
在因特网环境下验证客户端用户和服务
维护可以访问服务的合法用户及用户凭据需要不同形式数据库。在Windows环境下,活动目录提供了这样的一个数据库。WCF服务可以使用Windows集成身份验证的方式,来验证位于同一个域内的客户端用户。如果客户端程序通过一个公共网络连接到该服务,那么上述方式将不再适用。因为客户端程序很可能没有与服务运行在同一个安全域内。此时,你可以使用其他的方式来维护允许访问服务的用户列表。比如,你可以使用ASP.NET成员程序和ASP.NET角色程序。此外,你也可以使用授权存储角色程序(Authorization Store Role Provider)在XML文件中保存用户和角色。在本章的练习中,你将使用的是ASP.NET成员程序和ASP.NET角色程序。
使用ASP.NET成员程序和ASP.NET角色程序验证和授权用户
为了能通过因特网访问WCF,你将使用IIS来寄宿WCF服务。通过这种方式寄宿WCF服务,你可以使用ASP.NET Web站点管理工具容易地为WCF服务创建一个针对该服务的,管理用户和角色的SQL数据库。然后,你可以配置WCF服务使用ASP.NET成员程序验证用户,使用ASP.NET角色程序获取角色信息并授权用户。这就是你下面要做的练习。
另外,当你在因特网上发布服务时,你应该采用SSL来保护通信。因此,第一个任务是配置IIS,通过添加证书 使其支持SSL。该证书可以验证服务、加密服务与客户端之间的信息。然后,将该证书绑定到寄宿WCF服务的站点。
配置IIS的绑定使其支持SSL
1. 使用管理员身份运行IIS管理控制台。
2. 在IIS管理控制台中,在"连接"面板,点击你计算所在的节点。
3. 在中间面板,点击"特性"标签。
4. 在特性面板,双击"服务证书"。
双击之后,服务证书面板将出现,它列出了可以用来配置IIS实现SSL的所有证书。你可以看到之前我们在第四章创建的证书WcfHttps,我用红色方框标出了该证书。为了本章的测试目的,我们将新建另外一个证书。因为在不同的网站上使用同一个证书是不推荐的做法。
5. 在"操作"面板,点击"创建自签名证书"。将出现"创建自签名证书"对话框。该向导与第四章在visual studio 命令行中使用makecert命令结果一样,将会创建一个证书。与第四章的警告一样,提示你不要在产品环境中使用自签名证书。如果你需要一个商用证书,你应点击"操作"面板中的"创建证书请求"链接,创建一个识别你企业的证书请求,然后向证书提供商,比如活动目录证书服务或者信任的第三方机构,发送请求以生成该证书。
6. 在"创建自签名证书"对话框中,输入该证书的名字,然后点击"确认"按钮。
该证书将自动生成,并且添加到服务证书面板中,如下图所示
7. 在IIS管理控制台左边面板中,展开你的计算机名,然后在默认站点上点击右键,选择"编辑绑定":
将出现"编辑站点绑定"对话框。该对话框中列出了该站点IIS和WAS所支持的协议。
8. 在"编辑站点绑定"对话框中, 如果https还未配置,那么点击"添加"按钮,选择HTTPS,并选择刚才创建的证书。然后点击"确定"按钮。
9. 关闭"编辑站点绑定"对话框,并退出IIS管理控制台。
创建InternetProductsServcie站点
1. 在第五章的文件夹下(...\ Step.by.Step\Chapter5),添加一个空文件夹,命名为InternetProductsServcie.
2. 启动IIS管理控制台,然后创建一个web应用程序,其名字为"InternetProductsServcie",应用程序池使用ASP.NET V4.0,路径指向...\ Step.by.Step\Chapter5\InternetProductsService.
3. 在IIS管理控制台中,选中InternetProductsServcie,然后在击中间面板的"特性视图"标签下,双击SSL设置。
4. 在SSL设置面板中,选中"要求SSL"签名的复选框,然后点击"应用"
4. 确认该站点验证方式允许匿名访问
5. 保持IIS管理控制台处于打开的状态。
创建InternetProductsService解决方案
1. 启动Visual Studio,新建一个站点,选择类型为WCF服务,web位置选择HTTP,路径为https://localhost/InternetProductsService;
2. 建立好WCF站点后,删除IService.cs,Servcie.cs,Servcie.svc这三个文件;
3. 在该下过目上点击右键,添加已经存在的项目;将第四章的IProductsServcie.cs和ProductsService.cs添加进该项目。
4. 选择InternetProductsService;引用ProductsEntityModel.dll
5. 由于客户端将使用ASP.NET成员程序中创建的用户来访问InternetProductsServcie,所以需要修改ProductsService.cs文件
7. 编译InternetProductsService,确认没有警告和错误。
激活服务InternetProductsServcie和配置绑定
1. 启动Visual Studio,并打开站点InternetProductsService。
2. 使用WCF配置管理工具,打开web.config
3. 采用下面方式激活服务。展开"高级"文件夹,然后展开"宿主环境",选择"服务激活",在右边面板中点击"添加"按钮;在"服务激活编辑器"窗口中,设置"相对地址"为"Service.svc";输入择服务为Products.ProductsService.(如果出现消息提示对话框,请点击"确定"按钮继续);
4. 在WCF配置管理工具中,点击"服务"文件夹,然后点击"创建一个新服务"。输入服务类型为"Products.ProductsServcie",然后点击下一步,当出现警告时,点击"确定"按钮继续;
然后点击下一步,输入服务契约为"Products.IProductsService";选择"HTTP"传输协议,然后点击下一步
选择"高级web服务互操作",然后点击下一步;
输入地址为"https://localhost/InternetProductsServcie/Service.svc", 然后点击下一步;
确认无误后,点击"完成"按钮,完成服务的创建。
5. 创建一个名为"ProductsServiceWS2007HttpBindingConfig"绑定,该绑定使用ws2007HttpBinding协议;
6. 创建好该绑定后,选择该绑定,然后点击右边面板中的"安全"标签;并做如下相应的设置:
由于IIS设置使用HTTPS协议,因为WCF必须配置为支持传输安全。TransportWithMessageCredential模式使用在传输级别使用HTTPS协议保护消息的传输;并使用服务证书验证客户端;使用消息安全来验证用户凭据。用户名口令作为用户凭据传输至服务。
7. 在WCF配置管理工具中,选择服务端点,然后设置该端点使用ProductsServiceWS2007HttpBindingConfig绑定配置。
8. 在WCF配置管理工具中,选择"高级"—"服务行为"—"未命名"—"服务元数据",设置HttpGetEnabled为false,HttpsGetEnabled为true。
9. 保存设置,并退出WCF配置管理工具
10. 在Visual Studio中,打开web.config;找到<serviceHostingEnvironment>元素,设置multipleSiteBindingsEnabled属性的值为false
11. 保存web.config.
12. 测试网站,直接在浏览器中输入https://localhost/InternetProductsService/Service.svc,你将得到如下结果:
13. 关闭IE浏览器
到目前为止,你已经部署,配置和测试了IIS寄宿的WCF服务InternetProductsService。现在,你可以开始使用ASP.NET管理工具定义允许访问该WCF的用户和角色。为了简化,你将创建与第四章一样的角色(WarehouseStaff和StockControllers)和用户(Fred和Bert)。
为WCF服务InternetProductsServcie定义用户和角色
1. 在Visual Studio中,选择InternetProductsService站点,然后从菜单Website中选择ASP.NET配置;将启动ASP.NET站点管理工具网站:(注意,在使用这个步骤之前,请确保你的电脑已经按扎了SQL Server,并且使用aspnet_regsql注册了ASP.NET角色程序和ASP.NET成员程序。注册的本质就是在数据库中创建对应的表,以及在IIS中添加连接到该数据库的连接字符串。这样启动ASP.NET站点管理工具的时候,该工具就知道如何连接到数据库,并添加用户,角色,及你所配置的站点的相关信息)
2. 点击"安全"标签,站点将切换到"安全页"。在该页,你可以管理用户,指定站点所使用的验证机制,定义用户的角色,指定访问网站规则。
3. 点击"选择验证类型"连接,然后选择 "From the internet";点击点击"Done"按钮,回到"安全页"
4. 回到安全页后,你可以发现当前存在的用户为0,点击"创建用户"按钮,创建用户Bert,其密码为Pa$$w0rd;其他的选项可以随便输入。
5. 重复第四步,创建用户Fred;
6. 回到安全页,确认当前用户数为2;
7. 在页面的角色区域,点击"激活角色"链接;
8. 然后,点击"创建或管理角色"链接;然后输入WarehouseStaff
9. 创建WarehouseStaff角色后,点击"管理"连接
10. 在选择用户界面,将Bert和Fred添加到角色WareHouseStaff中
11. 创建角色StockControllers
12. 添加StockControllers角色后,将用户Fred添加至该角色
13. 关闭ASP.NET站点管理工具。
配置WCF服务使用ASP.NET角色程序和ASP.NET成员程序
1. 在visual studio中,使用WCF服务配置工具,打开InternetProductsServcie的web.config;
2.在配置面板中,展开"高级"—"服务端行为"—"未命名行为";然后在右边面板中点击"添加"按钮,在出现的对话框中,选择"serviceAuthorization",最后点击"确定"按钮。
3. 展开"未命名服务行为",选择"serviceAuthorization"。然后在右边面板中,设置PrincipalPermissionMode属性的值为UserAspNetRoles; RoleProviderName属性的值为AspNetSqlRoleProvider.
4. 再次选择"未命名服务行为",右键,选择"创建新的服务行为元素扩展",然后选择serviceCredentials,然后点击"添加"按钮。
5. 选中"serviceCredentials",然后在右边面板中设置MembershipProviderName属性的值为AspNetSqlMemberShipProvider; 设置UserNamePasswordValidationMode属性的值为MembershipProvider
6. 保存配置文件
7. 退出WCF服务配置工具。
修改WCF客户端程序使之能连接到InternetProductsServcie
1. 复制第四章的ProductsClient到第五章文件夹下;然后添加该项目到InternetProductsService解决方案中
2. 使用WCF服务配置工具打开项目ProductsClient的app.config
3. 选择左边面板中的"绑定",然后右键,选择"创建新的绑定配置",在出现的对话框中,选择ws2007HttpBinding;然后点击"确定"按钮。
4. 设置该绑定的名字为"ProductsClientWS2007HttpBindingConfig"
5. 切换到"安全"标签,设置模式为"TransportWithMessageCredential"; MessageClientCredentialType属性的值为UserName;TransportClientCredentialType为None
6. 在WCF服务配置工具中,选择端点"WS2007HttpBinding_IProductsServcie"; 然后设置该端点的地址为https://localhost/InternetProductsServcie/Servcie.svc; 并设置绑定配置属性的值为"ProductsClientWS2007HttpBindingConfig"
7. 保存设置,并退出WCF服务配置工具。
8. 配置ProductsClient使用对应的证书和端点
9. 添加客户端用户凭据
测试WCF服务
1. 运行ProductsClient,你会得到如下结果
2. 修改客户端用户凭据,使其使用Fred连接至InternetProductsService服务。你将得到如下结果:
3. 从上面可以看到,Fred可以执行changestocklevel操作,而Bert则不可以执行;这是因为Fred不仅属于WarehouseStaff组,还属于StcokController组;但Bert仅仅属于WarehouseStaff组。这是由于我们在服务上定义了只有StockController组才能执行changestocklevel操作。
4. 推出ProductsClient程序
注意:在做这个练习时,有几个地方主要注意
1. 在创建自签名证书后,如果你使用https://localhost/InternetProductsServcie/Servie.svc访问,那么IE将显示如下警告信息
这是因为自签名的正式是针对你的计算机名生成的证书。所以你应该使用https://yourcomputername/InternetProductsServcie/Servcie.svc来访问你的服务;那么将直接得到如下结果:
2. 服务端点的地址可以为空或相对地址。
如果服务端点的地址也为相对地址,那么会发生什么情况呢?WSDL中SOAP的地址将如下图所示:
3. 在配置服务的SSL证书时,为了避免重名的现象,可以使用通过GUID的方式来查找证书
4. 如何配置ASP.NET成员程序和角色程序。请参考MSDN:
- How to: Use the ASP.NET Membership Provider http://msdn.microsoft.com/en-us/library/ms731049.aspx
- How to: Use the ASP.NET Role Provider with a Service http://msdn.microsoft.com/en-us/library/aa702542.aspx
使用证书验证和授权用户
使用用户名和密码来验证用户在一定的程序上实现了安全,但是你很快就意识到这种实现方式的缺点。其非常容易将用户密码暴露给其他用户。由于许多人为了使密码便于记忆,他们所输入的密码要么非常简短,要么很容易猜测(比如1234, abcd,password等)。上诉密码还不如你把你妈妈仆人的名字作为密码,可能相对还安全一点;但在因特网环境中,该密码也是不适合的。这也就是当你通过因特网连接到银行时,银行为什么不采用用户名和密码来识别你的身份的原因。
使用公钥体系(PKI)能帮助克服密码的缺点。PKI提供消息加密和消息验证功能。
PKI基于一对密钥(一个密钥是一长串随机数字):一个用于加密消息的公钥;另一个用于解密的私钥。这些密钥都应是唯一的。如果你想与第三方组件通信,你可以向其发送一份公钥;第三方使用该公钥加密消息;然后将加密后的消息回传给你。你使用你的私钥解密这些加密的消息。
该理论认为:只有你的私钥可以解密使用你的公钥加密的消息。因为它不关心有人是否能破解你的消息,因为外人不能读到该消息(没有私钥)。而实际上,即使没有私钥,加密的消息也能被破解,当然这得花费相当大的气力;私钥的长度越长,其耗费的气力也就越多。
公钥和私钥还可以另外一种方式工作。你使用私钥加密消息,其他人使用公钥解密该消息。这听起来似乎不太有用;但其提供了用于验证消息来源的便利机制。假如第三方收到一个自称由你发送的加密消息;但是第三方不能使用你提供的公钥解密该消息;那么这就说明第三方收到的加密消息实际上是由别人冒充你而发送的;此时第三方应该丢弃该消息。
那么,你从哪里得到密钥呢?你可以从证书授权机构(CA)申请一对证书形式的密钥。CA将执行各种检查以确保证书拥有者是该证书的真正主人。如果通过检查,CA将为你颁布一个包含公钥和私钥的证书。这个证书还包含一些关于证书持有者和CA自身的身份信息。
现假设数字证书持证人甲向持证人已传送数字信息,为了保证信息传送的真实性、完整性和不可否认性,需要对要传送的信息进行数字加密和数字签名,其传送过程如下:
- 甲准好好要转送的数字信息(明文)
- 甲对数字信息进行哈希计算,得到一个信息摘要
- 甲用自己的私钥对信息摘要进行加密得到甲的数字签名,并将其附在数字信息上。
- 甲随机算出一个机密密钥DES,并用此密钥对要发送的信息进行加密,形成密文。
- 甲用乙的公钥贵刚才山城的加密密钥进行加密,将加密后的DES密钥连同密文一起传送给乙。
- 乙收到甲传送过来的密文和加过密的DES密钥,先用自己的私钥对加密的DES密钥进行解密,得到DES密钥。
- 乙然后用DES机密密钥对收到的密文进行解密,并得到信息摘要。
- 乙用相同的哈希算法对收到的明文再进行一次哈希运算,得到一个新的信息摘要
- 乙将收到的信息摘要和新产生的信息摘要进行比较,如果一直,说明收到的信息没有被修改过。
关于PKI的更多消息,请参考http://technet.microsoft.com/en-us/library/cc751024.aspx
服务可以使用一个证书让客户端验证该服务,以减少客户点连接到一个假冒的服务风险。你应该从一个值得你和参与者都信任的证书颁发机构获取一个证书用来识别自己并加密你的通讯;同时不要对外公布你的私钥。
在下面的练习中,你将看到如何使用证书来对消息签名,并且验证用户。
修改WCF服务,使其要求客户端程序使用证书验证用户
1. 使用Visual Studio打开InternetProductsServiceUserCert解决方案;然后使用WF配置管理工具打开web.config;
2. 展开绑定,选择ProductsServiceWS2007HttpBindingConfig,然后切换到"安全"标签,并设置MessageClientCredentialType为Certificate; 现在,WCF服务将要求客户端程序提供一个证书以验证该用户。NegotiateServiceCredential属性指定客户端程序如何向服务发送证书。如果该属性的值为true,WCF服务期望客户端程序将证书附加在消息内一起发送(实际上,当客户端和WCF服务交换证书的时候,将引发一系列的初始化消息)。如果改值为false,那么WCF服务的管理员必须手动安装客户端证书到运行该服务的计算机下的"信任人"证书存储位置上。
设置该值为false,你后面的练习中,你将手动安装客户端证书
3. 在配置管理工具左边面板,展开"高级"—"未命名"—"服务证书"— "客户端证书";设置属性"CertificateValidationMode"的值为"PertTrust"
客户端证书的验证方式有如下几种:
默认情况下,当验证证书时,服务将从证书存储位置LocalMachine处查找证书。如果你使用IIS寄宿WCF服务,那么这种方式有很效。如果你创建自寄宿WCF服务的程序,并且该程序是以某个特定的身份运行,你可以配置WCF在证书存储位置CurrentUser处查找证书。
RevocationMode用于指定X509证书吊销检查的模式;其包含下列可能值:
6. 保存设置,并推出WCF配置管理工具
配置客户端以供WCF服务使用客户端证书验证客户端
1. 使用WCF配置工具打开ProductsClinet的app.config
2. 在配置面板下,展开绑定,选择ProductsClientWS2007HttpBindingConfig;然后在右边面板切换到"安全"标签。设置MessageClientCredentialType属性的值为Certificate;并设置NegotiateServcieCredential为False。
3. 保存设置,并退出WCF配置管理工具
创建证书以共WCF服务识别测试用户
1. 使用管理员身份运行Visual Studio Command Prompt
2. 执行下图所示的两个命令,分别创建subject为Bert和Fred的证书
你所创建的上述两个证书将存储在证书存储位置CurrentUser下的Personal certificate处。WCF服务要求管理员安装这两个证书的副本到运行WCF服务计算机上的证书存储位置Truested People下。在下面的练习中,我们将导出刚刚创建的两个证书的副本,然后将证书副本导入到本地计算机上的证书存储位置Trusted People下。
导出与导入证书
1. 在Visual Studio Command Prompt,执行下面的命令
上面第一个命令的作用是从当前计算机证书存储位置Currentuser下的Personal certificate处获取Bert证书的副本。该副本包含原证书的公钥,不包含原证书的私钥。第二个命令是导入Bert证书副本至当前计算机的证书存贮位置LocalMachine下的Trusted people处。第三个和第四个命令是重复前面两个命令,只不过操作的是证书Fred。
2. 退出Visual Studio Command Prompt
3. 在开始—运行,输入certmgr;你可以查看Bert和Fred的证书副本是否已经导入到LocalMachine下的Trusted people处。
如果你在点击原始证书,你可以发现原始证书和证书副本的差别在于是否包含私钥(原始证书的图标上有一把钥匙。下图左边是原始证书,右边是证书副本)。
更新WCF客户端,使其向WCF服务发送证书
1. 在visual studio中,打开ProductsClient下的program.cs文件
2. 做如下修改
3. 然后生成该项目;并运行ProductsClient,你会得到如下结果:
这说明WCF服务已经验证了客户端(如果未通过验证,你将收到验证失败的异常),无权访问的原因在于存贮在SQL数据库中的角色信息还未更新。用户Bert未能获取到相应的授权 。
4. 退出ProductsClient
现在,你将更新SQL Server数据库,添加用户和角色的定义,使其映射到从客户端证书中获取的用户和角色。首先,你应该理解当客户端使用证书验证自己时,WCF服务所识别的客户端的身份。
调查使用客户端证书时,访问WCF服务的客户端用户的身份信息
1. 开发InternetProductsSercie项目中app_code文件夹下的ProductsServcie.cs文件
2. 注释掉ListProducts的PrincipalPermission和ListProducts的内容,然后添加下列新的语句
3. 生成项目,然后运行ProductsClient,你将得到如下结果:
WCF服务验证后的客户端身份包含两部分内容:subject名字和证书的thumbprint值。 Thumbprint值是该证书的唯一标识符。该值将被保存到SQL Server数据库中,并供ASP.NET角色程序使用。
4. 退出ProductsClient。
更新SQL Server数据库中用户信息
1. 在Visual Studio中,选择InternetProductsServcie,然后从Visual Studio的菜单中,选择站点—ASP.NET站点配置工具
2. 在ASP.NET站点配置工具中,点击"安全"标签,以切换到"安全页"
3. 点击创建用户连接,进入创建用户界面;
在用户名处输入"CN=Bert; 64106fcaa45093f01739c82d8280c39153b5559b",后面的那一串字符为证书的Thumbprint的值(已经去除空格);改制就是上面实验结果中客户端使用证书时的身份。然后确认角色WarehoustStaff被选中;
然后点击"创建用户"按钮,完成用户创建。
4. 你再次运行ProductsClient,你将会得到如下结果:
5. 添加用户Fred,并将其添加角色StockControllers和WarehouseStaff;
6. 修改program.cs使用证书Fred去访问InternetProductsService,将得到如下结果:
使用证书验证服务的消息
当服务使用HTTPS协议时,确保了客户端与服务端之间通信的保密性。服务向客户端发送一个证书,该证书包含一个用于加密通信的公钥;客户端程序验证服务端发送过来的证书是否来自CA。但是,HTTPS主要用于确保通信的保密性。以验证建立SSL对话为目的的验证(传输级别验证)和基于消息级别的验证不同,后者能验证消息发送者的身份。客户端程序通常假设其将消息发送至一个特定的,可信任的服务,但是该假设是否真的有效呢?客户端可能实际上与一个冒牌的服务以一种安全的方式交换消息,因为黑客可以入侵DNS服务器,并且将发送至真实服务的消息转发至其他任何地方。为了避免这种情况的发生,你需要通过双向验证来实施消息安全取代传输安全。
验证服务和服务验证客户端很相似。服务使用私钥签名一个消息并发送至客户端,客户端从自己的证书存贮位置上获取服务端证书副本中的公钥,然后使用此公钥来解密消息并验证服务的签名。如果解密消息失败,那么服务的签名不可识别,因此客户端拒绝该服务发送的消息。与第四章中使用消息安全一样的方式,服务和客户端之间的所有通信也已经加密。
在下面的 练习中,你将创建另外一个ASP.NET站点寄宿WCF服务;然后,你将配置该服务使用消息安全,以使客户端可以验证该WCF服务发送的消息。
创建一个将实施消息安全的ASP.NET站点
1. 打开IIS管理控制台
2. 建立一个MutualAuthenticationProductsServcie的新站点,该站点使用ASP.NET v4.0应用程序池,并且指向对应的文件夹。
配置WCF服务使用localhost证书验证自己
1. 使用管理员设分身运行Visual Studio Command Prompt; 并执行下面命令
上述命名创建一个subject为localhost的证书,并且存放在证书存储位置LocalMachine下的Personal处。Subjet名字必须和客户端连接到服务所使用URL中的主机名相匹配。
如果你使用IIS来寄宿WCF服务,那么你必须确认NETWORKSERVICE帐号有证书的读取权限。如果你使用其他程序自我寄宿服务,那么可以忽略下面步骤
2. 转到目录WCF\Step.by.Step\Chpater5,执行下面命令
FindPrivateKey工具显示了我们在第一步所创建证书的私钥信息。FindPrivateKey是WCF Samples所提供的一个工具。你可以从微软站点下载到。上述命令结果显示的文件就是我们要为NETWORKSERVICE添加权限的文件。关于FindpriveteKey更多信息,请参考http://msdn.microsoft.com/en-us/library/aa717039.aspx
3. 执行下列命令,为NETWORKSERVICE添加读权限
请注意,执行该命令的前提是当前运行ASP.NET V4.0的帐号为NETWORKSERVICE,如果为其他用户,请为对应的帐号添加读的权限。
4. 输入"IISRESET"重启IIS
5. 使用Visual studio打开站点MutualAuthenticationProductsServcie
6. 使用WCF服务配置管理工具打开WEB.CONFIG
7. 设置安全模式为"Message"
8. 在WCF配置管理工具中,选择高级—服务行为—未命名—服务凭证—服务证书;然后在右边面板中,设置FindValue为localhost, X509FindType为FindBySubjectName
9. 保存设置,并退出WCF配置管理工具
导出WCF服务证书,并导入到客户端证书的存储位置上
1. 用管理员身份执行Visual Studio Command Prompt,然后执行下列命令
上述命名将获取localhost证书的副本。该副本包含原证书的公钥,并未包含私钥信息。
2. 执行下面的命令,导入localhost证书的副本到证书存储地CurrentUser处
配置WCF客户端使其验证WCF服务
1. 使用Visual Studio,添加ProductsClient程序
2. 使用WCF服务配置管理工具,打开ProductsClient的app.config
3. 设置端点地址为http://localhost/MutualAuthenticationProductsServcie/Service.svc
4. 修改绑定ProductsClientWS2007HttpBindingConfig的安全模式为Message
5. 添加端点行为配置。展开高级—端点行为,右键选择"添加端点行为配置"
6. 设置该端点配置的名字为"AuthentiationBehavor";然后点击右边面板下方的"添加"按钮,添加clientCredential元素
7. 选择AuthentiationBehavior--客户端凭据—客户端证书;在右边的面板中设置FindValue为localhost,设置X509FindType为FindBySubjectName
8. 设置端点WS2007HttpBinding_IProductsService使用上述创建的端点行为
9. 保存设置,并退出WCF配置管理工具
10. 修改program.cs
确认客户端验证WCF服务
1. 运行ProductsClient,你将会得到如下结果
2. 按回车键退出ProductsClient
3. 在Visual studio Command Prompt中运行下面的命令以移除证书localhost
4. 然后再运行下面命令创建另外一个subject名相同的证书
5. 输入IISRESET重启IIS
6. 你再一次运行ProductsClient,你将得到如下错误
由于WCF服务所使用的证书localhost中的用于消息的私钥已经发生改变,因此客户端不能使用之前localhost证书副本中的公钥去验证服务端发送的消息中的签名。该场景模拟了真实的WCF服务别其他服务替换的场景。
如果你想ProductsClient能正常运行,那么你需要做的是,导出新创建的localhost证书副本;删除证书存储位置CurrentUser下的之前的localhost证书副本;然后再导入新的localhost证书副本。
7.按enter键退出ProductsClient
识别服务
上述例子展示了如何配置消息安全,而且授权发生在消息对消息的基础上。其要求管理WCF服务的管理员必须为连接到该WCF服务的客户端发送该WCF服务使用证书的公钥;并且配置客户端使用该公钥验证服务。该机制非常安全,但是增强的安全以加密和签名所有通信为代价。一个可替换的解决方法是,你可以实施服务验证。这种方式不要求保护消息。但是它可以确保客户端以一定程度的保密地方式连接到真实服务。
当你配置客户端端点时,你可以在<identity>元素中指定期望的服务身份。根据服务的安全设置要求,该值可以是证书,或者主机的DNS名称,或者RSA,或者SPN,甚至UPN指定服务运行的账户。 下面的例子显示了如何执行服务的SPN
当客户端程序运行并连接至服务时,WCF运行时要求服务的身份并验证服务的身份和客户端配置文件中的身份是否一致;这一切发生在客户端向服务发送第一个消息之前。如果身份匹配,那么服务开始验证客户端,当客户端通过验证后,客户端运行和服务之间收发消息。如果身份不一致,那么服务将被当作一个冒牌的服务,客户端将将不做进一步处理
【总结】
在本章,你已经了解到当WCF服务运行在不同的Windows域下时,如何验证和授权客户端用户。你还了解到如何配置ASP.NET成员程序使用SQL数据中存贮的用户凭据来验证用户;以及如何配置ASP.NET角色程序来指定用户的角色以完成WCF服务的授权。你还理解了客户端和服务如何通过证书来验证彼此收发的消息;并且明白了两者如何分别使用公钥和私钥进行通信以远离网络中潜在的威胁。最后,你看到了如何在客户端程序中如何设置服务的身份以供WCF运行时检查客户端连接到的服务是否是真实的服务。