在Azure上搭载以SSL方式访问的WcfService
搭载SSL的WcfService的方法:
创建一个Azure项目CollectorWebService和一个WcfService项目CollectorWebServiceRole。这两个项目都已经在Http下能正常访问。下面要把该WcfService修改为支持SSL的WcfService。
一、制作SSL的证书
该证书必须满足一下条件:
1、 该证书必须包含私钥
2、 该证书必须是支持密钥交换的.pfx文件
3、 该证书的subject必须匹配你发布的WcfService的域名,如:CloudMgr.cloudapp.net,而不能仅是cloudapp.net。
4、 该证书必须是最低2048位加密。
在Visual Studio Tools中启动Visual Studio命令行工具,制作证书的命令:
makecert -sky exchange -r -n "CN=CloudMgr.cloudapp.net" -pe -a sha1 -len 2048 -ss My "CloudMgr.cloudapp.net.cer"
此文,是以 CloudMgr.cloudapp.net为例制作的证书,在实际应用中自己需要根据相应Role的名称更改名称,YourAppName.cloudapp.net。
关于数字证书更多的信息,请参考 在.NET中操作数字证书 http://blog.csdn.net/zztfj/article/details/6036869
然后,在“开始”菜单的“运行”中输入“certmgr.msc”进入“证书管理”的控制台页面。在“个人”文件夹下找到刚才创建的CloudMgr.cloudapp.net证书,右键“所有任务”——“导出”,输入在创建证书的时候输入的密码,即可导出.pfx文件。
二、上传该.pfx文件。
在Azure Management Portal中,创建CloudMgr的HostedService,然后,点击“添加证书”,选择刚才生成的.pfx文件,并输入对应的密码。
上传成功后,复制该证书的thumbprint以备用。
三、设置项目配置文件使其支持SSL。
1、依据下面的配置修改.csdef文件
<WebRole name="CollectorWebServiceRole" vmsize="Small"> <Sites> <Site name="Web"> <Bindings> <Binding name="Endpoint1" endpointName="Endpoint1" /> </Bindings> </Site> </Sites> <!--HTTPS SSL通信方式--> <Certificates> <Certificate name="CloudMgr.cloudapp.net" storeLocation="LocalMachine" storeName="CA" /> </Certificates> <Endpoints> <InputEndpoint name="Endpoint1" protocol="https" port="443" certificate="CloudMgr.cloudapp.net" /> </Endpoints> <!--HTTPS SSL 通信方式--> <!—HTTP 通信方式--> <!--<Endpoints> <InputEndpoint name="Endpoint1" protocol="http" port="80" /> </Endpoints>--> <!—HTTP 通信方式--> <Imports> <Import moduleName="Diagnostics" /> </Imports> <LocalResources> <LocalStorage name="CollectorWebServiceRole.svclog" sizeInMB="1000" cleanOnRoleRecycle="false" /> </LocalResources> <ConfigurationSettings> </ConfigurationSettings> </WebRole>
2、依据下面的配置修改.cscfg文件
<Role name="CollectorWebServiceRole"> <Instances count="1" /> <ConfigurationSettings> <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" /> </ConfigurationSettings> <!--HTTPS SSL 通信方式--> <Certificates> <Certificate name="CloudMgr.cloudapp.net" thumbprint="9F11154439992F3AD04951E98175D7FFA72EDBAB" thumbprintAlgorithm="sha1" /> </Certificates> <!--HTTPS SSL 通信方式--> </Role>
依据上面的步骤部署该WcfService后,会出现下面的错误提示:
在Role工程的web.config文件中追加了下面的内容后,问题解决。
<!--HTTPS SSL 通信方式--> <system.serviceModel> <bindings> <basicHttpBinding> <binding name="BasicHttpBinding_IService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true"> <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <security mode="Transport"> <transport clientCredentialType="None" proxyCredentialType="None" realm="" /> <message clientCredentialType="UserName" algorithmSuite="Default" /> </security> </binding> </basicHttpBinding> </bindings> <services> <service name="CollectorWebServiceRole.Service"> <endpoint address= "" binding="basicHttpBinding" contract="CollectorWebServiceRole.IService" bindingConfiguration="BasicHttpBinding_IService" /> <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/> </service> </services> <behaviors> <serviceBehaviors> <behavior> <serviceMetadata httpsGetEnabled = "True"/> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors> <serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> </system.serviceModel> <!--HTTPS SSL 通信方式--> <!--HTTP 通信方式--> <!--<system.serviceModel> <bindings> <basicHttpBinding> <binding name="BasicHttpBinding_IService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true"> <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> </binding> </basicHttpBinding> </bindings> <services> <service name="CollectorWebServiceRole.Service"> <endpoint address= "" binding="basicHttpBinding" contract="CollectorWebServiceRole.IService" bindingConfiguration="BasicHttpBinding_IService" /> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> <behaviors> <serviceBehaviors> <behavior> <serviceMetadata httpGetEnabled = "True"/> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors> <serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> </system.serviceModel>--> <!--HTTP 通信方式-->
创建一个AzureWorker调用该AzureWcfService
创建一个AzureWorkerRole的工程,在该工程中“引用服务”,添加引用上面创建的WcfService,该步骤会自动生成一个本地代理类。现在要做的就是使该代理类在向使用SSL的WcfService进行信息交互的时候使用指定的证书。
在引用WcfService之后,依据下面的配置修改app.config文件
<system.serviceModel> <bindings> <basicHttpBinding> <binding name="BasicHttpBinding_IService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true"> <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <!--HTTPS SSL 通信方式--> <security mode="Transport"> <transport clientCredentialType="None" proxyCredentialType="None" realm="" /> <message clientCredentialType="UserName" algorithmSuite="Default" /> </security> <!--HTTPS SSL 通信方式--> </binding> </basicHttpBinding> </bindings> <client> <endpoint address="https://cloudmgr.cloudapp.net/service.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService" contract="CollectorService.IService" name="BasicHttpBinding_IService" /> </client> </system.serviceModel>
把生成的.cer证书文件放在该WorkerRole工程下,修改文件的属性为“常复制”,使该证书与该工程一同发布。
修改代码使WcfService的代理类发送请求前使用证书。
//向WcfService发送消息 using (CollectorService.ServiceClient client = new CollectorService.ServiceClient()) { //HTTPS SSL 通信方式,如果是Http通信,请删除该部分 client.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2(X509Certificate2.CreateFromCertFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "CloudMgr.cloudapp.net.cer"))); ServicePointManager.ServerCertificateValidationCallback += RemoteCertificateValidate; //HTTPS SSL 通信方式,如果是Http通信,请删除该部分 client.Post(data); } /// <summary> /// Remotes the certificate validate. /// </summary> private static bool RemoteCertificateValidate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error) { //信任现在客户端使用的证书。为了解决下面这个错误:Could not establish trust relationship for the SSL/TLS secure channel with authority // trust any certificate!!! System.Console.WriteLine("Warning, trust any certificate"); return true; }
至此,一个支持SSL方式访问的Azure服务和调用该服务的WorkerRole已经完成。
参考URL:
https://www.windowsazure.com/en-us/develop/net/common-tasks/enable-ssl/
http://watwindows8.codeplex.com/wikipage?title=Appendix%20I%3a%20How%20to%20Deploy%20Your%20Services%20to%20Windows%20Azure%3f&version=3