Silverlight跨域訪問Https下的Self-hosted WCF服務

來源:互聯網
上載者:User

跨域訪問(Cross Domain)在Silverlight中是個非常討厭的話題,常常在不經意間就會發現出現跨域訪問的問題。在某些特殊的情況下,你的網站以及服務可能部署在HTTPS的安全環境下,例如伺服器使用了VMWare或者F5等軟體來讓所有對於服務的請求都自動變成HTTPS請求,這個時候對於跨域訪問的設定以及服務端和用戶端的配置都有所不同。本文就著重講述了這樣情況下如何配置跨域訪問並如何解決常見的請求異常。

   

環境:Windows Server 2008 R2 + VMWare Tools(Https) + .NET Framework 3.5 + Silverlight 4. 因為使用了VMWare的軟體使得所有外部對本伺服器的Web請求均自動變為Https請求。在但IIS仍然可以區分在外部請求時是使用Https還是Http。

   

問題: An error occurred while trying to make a request to URI 'http://cn.mydomain.com/Allan/Services/ModelService.svc/main'. This could be due to attempting to access a service in a cross-domain way without a proper cross-domain policy in place, or a policy that is unsuitable for SOAP services. You may need to contact the owner of the service to publish a cross-domain policy file and to ensure it allows SOAP-related HTTP headers to be sent. This error may also be caused by using internal types in the web service proxy without using the InternalsVisibleToAttribute attribute. Please see the inner exception for more details.

   

用戶端配置:

<bindings>

<basicHttpBinding>

<binding name="BasicHttpBinding_IModelService" maxBufferSize="2147483647"

maxReceivedMessageSize="2147483647">

</binding>

</basicHttpBinding>

</bindings>

   

<client>

<endpoint address="http://cn.mydomain.com/Allan/Services/ModelService.svc/main"

binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IModelService"

contract="ModelServices.IModelService" name="BasicHttpBinding_IModelService" />

</client>

   

此時我們將服務地址設為http,但得到的結果卻是可能Security Error,也可能是跨域訪問的問題。啟動Fiddler看看到底發生了什麼:

很明顯,ClientAccessPolicy.xml(以及CrossDomain.xml)無法被訪問,而請求結果是301錯誤:Moved Permanently。因為在Silverlight中設定的地址是http://cn.mydomain.com/...則對應的兩個跨域訪問的xml檔案也應該是http,所以這個請求應該是http://cn.mydomain.com/clientaccesspolicy.xml,但提示我們已經被永久轉向到https://cn.mydomain.com/clientaccesspolicy.xml,那說明我們應該將服務要求地址設定為https訪問就可以了。怎麼解決呢?

   

<bindings>

<basicHttpBinding>

<binding name="BasicHttpBinding_IModelService" maxBufferSize="2147483647"

maxReceivedMessageSize="2147483647">

<security mode="Transport" />

</binding>

</basicHttpBinding>

</bindings>

   

<client>

<endpoint address="https://cn.mydomain.com/Allan/Services/ModelService.svc/main"

binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IModelService"

contract="ModelServices.IModelService" name="BasicHttpBinding_IModelService" />

</client>

   

但是很奇怪的是你的請求沒有被順利的傳輸到服務端,而且在Fiddler中觀察的結果也是500錯誤,無法被請求。有時你也會得到這樣的錯誤:

Could not find a base address that matches scheme https for the endpoint with binding BasicHttpBinding. Registered base address schemes are [http].

   

那麼,問題在哪兒呢?

  1. 首先,預設情況下https的請求是不被跨域存取原則所接受的,需要特殊設定。
  2. 需要確保用戶端的security mode設定為Transport。(某些環境下server端的security需要設定為None)
  3. 在服務端設定BaseAddress。
  4. 完整的ClientAccessPolicy.xml和CrossDomain.xml,正確的路徑(位於網站根目錄下)

   

ClientAccessPolicy.xml檔案:

<?xml version="1.0" encoding="utf-8" ?>

<access-policy>

<cross-domain-access>

<policy>

<allow-from http-request-headers="*">

<domain uri="http://*"/>

<domain uri="https://*" />

</allow-from>

<grant-to>

<resource path="/" include-subpaths="true"/>

</grant-to>

</policy>

</cross-domain-access>

</access-policy>

   

CrossDomain.xml檔案:

<?xml version="1.0"?>

<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">

<cross-domain-policy>

<allow-access-from domain=""*"" />

<allow-http-request-headers-from domain=""*"" headers=""*"" />

</cross-domain-policy>

   

用戶端設定檔:

<system.serviceModel>

<bindings>

<binding name="BasicHttpBinding_IModelService" maxBufferSize="2147483647"

maxReceivedMessageSize="2147483647">

<security mode="Transport" />

</binding>

</basicHttpBinding>

</bindings>

   

<client>

<endpoint address="https://cn.mydomain.com/Allan/Services/ModelService.svc/main"

binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IModelService"

contract="ModelServices.IModelService" name="BasicHttpBinding_IModelService" />

</client>

</system.serviceModel>

   

服務端設定檔:

<system.serviceModel>

   

<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

<behaviors>

<serviceBehaviors>

<behavior name="defaultBehavior">

<serviceMetadata httpGetEnabled="true"/>

<serviceDebug includeExceptionDetailInFaults="true"/>

</behavior>

</serviceBehaviors>

</behaviors>

 

<bindings>

<basicHttpBinding>

<binding name="HyattSite.Services.ModelService.customBinding0">

<security mode="None"></security>

</binding>

</basicHttpBinding>

</bindings>

 

<services>

<service behaviorConfiguration="defaultBehavior" name="HyattSite.Services.ModelService">

<endpoint address="main" binding="basicHttpBinding" bindingConfiguration="HyattSite.Services.ModelService.customBinding0"

contract="HyattSite.Services.IModelService" />

<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />

   

<host>

<baseAddresses>

<add baseAddress="https://cn.mydomain.com" />

</baseAddresses>

</host>

</service>

</services>

</system.serviceModel>

   

OK, 大功告成,Silverlight可以正確的得到返回結果:

   

但是對於每個伺服器的環境可能是不一樣的,如果你在伺服器內部的訪問請求需要帶上許可權的話,那就更為麻煩一些。How To: SSL Passthrough with WCF --or-- TransportWithMessageCredential over plain HTTP 這篇文章可以帶給你更多的思路。

   

有關Cross Domain設定檔的更多資訊參閱:Cross-domain Policy File Specification

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.