2012-08-14 183 views
4

,我發現了錯誤:ASP.net同源策略頭不起作用

XMLHttpRequest cannot load http://www.scirra.com/handlers/arcadeProcessScore.ashx. Origin http://static1.scirra.net is not allowed by Access-Control-Allow-Origin. 

arcadeProcessScore.ashx我有臺詞:

public void ProcessRequest (HttpContext context) { 

    context.Response.AppendHeader("Access-Control-Allow-Origin", "http://static1.scirra.net"); 
    context.Response.AppendHeader("Access-Control-Allow-Origin", "https://static1.scirra.net"); 
    context.Response.ContentType = "text/plain"; 

然而,錯誤仍然存​​在。

我也試着簡單:

context.Response.AppendHeader("Access-Control-Allow-Origin", "*"); 

這也不起作用。

如果我在web.config級別添加<add name="Access-Control-Allow-Origin" value="*"/>它可行,但顯然不是解決方案。

我該如何讓arcadeProcessScore.ashx接受static1.scirra.net的請求?謝謝你的幫助。

回答

5

我做一些我自己的測試,直接使用XmlHttpRequest在我的項目進入處理程序。我使用的設置是將應用程序發佈到本地IIS(6.1版本,因此可能與7.5的行爲有所不同),並讓Default.aspx頁面調用我的處理程序在Visual Studio中的開發服務器中運行。就像這樣:

http://mymachine/WebTest/Default.aspx 

-> XmlHttpRequest get request to 

http://localhost:58025/WebTest/TestHandler.ashx 

代碼的處理程序:

public void ProcessRequest (HttpContext context) { 
    context.Response.AppendHeader("Access-Control-Allow-Origin", "http://mymachine"); 
    context.Response.Cache.SetCacheability(HttpCacheability.NoCache); 
    context.Response.ContentType = "text/plain"; 
    context.Response.Write("Hello World " + DateTime.Now.ToString()); 
} 

使用IE9時,behviour是一樣的,不管我是否沒有發送Access-Control-Allow-Origin頭球回處理。 IE9發出警告,要求用戶確認是否應加載內容。

Chrome(版本21.0.1180.79 m)和FF(版本14.0.1)實際上都會生成對處理程序的請求,並處理處理程序發回的標頭。

所以這個曾與Chrome和FF:

context.Response.AppendHeader("Access-Control-Allow-Origin", "http://mymachine"); 

所以這樣做:

context.Response.AppendHeader("Access-Control-Allow-Origin", "*"); 

但我一直沒能得到任何一方的顯示內容,如果我嘗試添加同一迴應中有幾種不同的允許來源。對我來說,沒有這些工作:

  1. 添加一些響應頭

    context.Response.AppendHeader("Access-Control-Allow-Origin", "http://mymachine"); 
    context.Response.AppendHeader("Access-Control-Allow-Origin", "http://someothermachine"); 
    
  2. 添加一個標題,用逗號隔開

    context.Response.AppendHeader("Access-Control-Allow-Origin", "http://mymachine, http://someothermachine"); 
    
  3. 添加一個頭的兩種來源,二起源空間分開

    context.Response.AppendHeader("Access-Control-Allow-Origin", "http://mymachine http://someothermachine"); 
    
  4. 添加一個頭兩個來源空格分隔

    context.Response.AppendHeader("Access-Control-Allow-Origin", "http://mymachine; http://someothermachine"); 
    

爲了得到它的工作,我所做的就是遵循this answer給出的建議。然後我的處理程序是這樣的:

public void ProcessRequest(HttpContext context) 
{ 
    string[] allowedOrigins = new string[] { "http://mymachine", "http://someothermachine" }; 
    string origin = context.Request.Headers.Get("Origin"); 
    if (allowedOrigins.Contains(origin)) 
     context.Response.AppendHeader("Access-Control-Allow-Origin", origin); 
    context.Response.Cache.SetCacheability(HttpCacheability.NoCache); 
    context.Response.ContentType = "text/plain"; 
    context.Response.Write("Hello World " + DateTime.Now.ToString()); 
} 

有了這個,Chrome和FF接受來自起源處理程序的輸出。

+0

工程很好,謝謝! IE限制是可以接受的。 – 2012-08-20 13:51:20

+1

這是我解決我的問題的一部分。儘管我使用的代碼非常類似於此處列出的代碼,但Chrome仍在拋出原始問題。我的問題發生是因爲我的**代碼都設置了Access-Control-Allow-Origin頭文件**並且** 在我的網絡配置。一旦我從我的網頁配置中刪除了該行,我就開始運行了。 – Garry 2012-12-19 00:53:32

1

您可以將web.config項目包裹在位置標記中,以便它僅在您的ashx位置運行,而且不會在其他地方運行 - 是否會緩解「objviously not the answer」問題?

<location path="~/path/to/handler/arcadeProcessScore.ashx"> 
<httpProtocol> 
    <customHeaders> 
     <clear /> 
     <add name="Access-Control-Allow-Origin" value="http://static1.scirra.net" /> 
    </customHeaders> 
</httpProtocol> 
</location> 
+0

這似乎不起作用,拋出500錯誤 – 2012-08-20 13:44:32

3

在這裏與您的代碼的問題是,跨源響應頭被髮送到瀏覽器實際要求,而它必須在那裏作出的實際要求之前!

W3 recommends用戶代理在提交實際上跨源HTTP請求之前實現一個預檢要求,這意味着,或者響應於包含實際請求,或以公知的作爲一個簡單的請求的響應的頁面預檢請求(在實際請求之前製作)必須包含Cross Origin響應標頭,當發出實際請求時。

跨源頭從預檢要求被存儲在預檢結果緩存返回。當一個跨源的HTTP請求時,用戶代理檢查在預檢結果緩存Access-Control-Allow-Origin頭,如果它不存在拋出一個異常,指出:

can not load address, Origin address is not allowed by Access-Control-Allow-Origin.

當你把Access-Control-Allow-Origin頭在web.config中,從服務器返回的任何響應包含Access-Control-Allow-Origin標頭,並且瀏覽器提交實際的跨域請求。

最好的辦法是在調用實際的跨域請求之前進行簡單的ajax調用(預檢請求),併發送該預檢請求所需的任何響應頭。