2012-05-23 77 views
28

我想在我的WebAPI項目中啓用CORS支持,如果啓用匿名身份驗證,那麼一切正常,但使用Windows身份驗證+禁用匿名身份驗證,OPTIONS請求發送總是返回401未經授權的迴應。請求它的網站在DOMAIN上,因此應該可以撥打電話,有沒有辦法在不禁用Windows身份驗證的情況下解決問題?響應IIS啓用Windows身份驗證的CORS請求

+0

您是否確認機器上是否支持集成Windows身份驗證? [http://technet.microsoft.com/en-us/library/cc754628%28v=WS.10%29.aspx](http://technet.microsoft.com/en-us/library/cc754628%28v= WS.10%29.aspx) –

+0

是的,運行在W7旗艦版和Server 2008上。我會貼上我從MS獲得的回覆,看起來可能,只是不容易,我們將切換到一個更多的oauth風格,並將我們的API分離爲允許匿名認證,但頒發授權令牌。 – dariusriggins

回答

11

從MS:

如果禁用匿名身份驗證,這是由設計,IIS會返回一個401的任何請求。如果他們啓用了Windows身份驗證,那麼在這種情況下,401響應將具有WWW-Authenticate頭,以允許客戶端啓動身份驗證握手。問題就出現在客戶正在使用的客戶端是否可以執行Windows身份驗證。

最後,似乎可能存在一個潛在問題,關於是否可以配置一個URL,使得一個動詞(本例中爲OPTIONS)允許匿名訪問,但需要其他動詞的Windows認證。 IIS不支持通過簡單的配置。通過啓用匿名和Windows身份驗證,在拒絕訪問匿名用戶的內容上設置ACL,然後配置有問題的URL的處理程序映射,以便它不驗證是否存在與該URL關聯的文件。但這需要一些玩家來證實這一點。

+2

剛注意到很多人在Web API受到Windows身份驗證等保護時遇到了401錯誤。 CORS預檢請求不包含憑據,因此即使在ASP.NET接觸它們之前,IIS也會以401.2響應。一個骯髒的解決方法是編寫一個HTTP模塊並掛接到IIS管道,該管道在'HttpApplication.BeginRequest'事件上註冊,其中此模塊返回預檢請求的預期200響應。此解決方法僅適用於IIS 7+集成模式。可悲的是微軟的支持可能不知道這個提示。 –

+1

剛剛發了一篇博文,https://blog.lextudio.com/2014/11/how-to-handle-cors-preflight-requests-in-asp-net-mvcweb-api-with-windows-authentication/ with有關IIS 6和經典模式用戶的更多信息。 –

+0

@LexLi閱讀你的博客,但不幸的是,你沒有詳細說明BeginRequest事件的確切實現,所以我不清楚200響應中包含哪些內容(例如標題等)。我瞭解如何構建HttpModules,只是想澄清要對預檢請求做出什麼響應。 –

3

由於IE 10 and 11中的錯誤,我今天遇到了同樣的問題,我使用的是ServiceStack而不是WebApi,但該方法也適用於您。

  1. 在IIS網站上啓用Windows集成和匿名身份驗證。
  2. 有一系列的ServiceStack管道過濾器,
    • 爲了處理一個Cors和OPTIONS請求,在選項的要求,我想補充必要的頭和結束的請求,檢查includng的HttpRequest被驗證
    • 過濾器?
    • 等過濾,

通過所有過濾器後,它執行的服務。

CorsFeature.cs

AuthenticateFilter

在我APPHOST,

appHost.Plugins.Add(new CorsFeature()); 

appHost.RequestFilters.Add(AuthenticateFilter.Authenticate); 

我已經修改了CorsFeature處理除了OptionsRequest對添加標題,驗證器檢查認證的請求!

+0

嗨,你能詳細介紹一下你做了什麼嗎?我面臨類似的問題,並且還使用通過SharePoint 2013部署的ServiceStack – link64

+1

我正在跳過檢查用戶是否對OPTIONS請求進行了身份驗證。我將添加代碼示例。 –

33

對於匿名用戶,您只能允許OPTIONS動詞。

<system.web> 
    <authentication mode="Windows" /> 
    <authorization> 
     <allow verbs="OPTIONS" users="*"/> 
     <deny users="?" /> 
    </authorization> 
</system.web> 

根據W3C規範,瀏覽器從排除預檢CORS的用戶憑據:https://dvcs.w3.org/hg/cors/raw-file/tip/Overview.html#preflight-request

+1

這是否需要在IIS中啓用匿名身份驗證模塊? – UserControl

+6

顯然是的。 「匿名身份驗證使用戶可以訪問Web或FTP站點的公共區域,而無需提示用戶輸入用戶名或密碼。」 http://bit.ly/1wjLdO9 –

+2

這應該是被接受的答案。 – slashp

13

事隔多年,但通過從@dariusriggins的答案,@法立我已成功地將下面的代碼添加到我的Global.asax:

public void Application_BeginRequest(object sender, EventArgs e) 
    { 
     string httpOrigin = Request.Params["HTTP_ORIGIN"]; 
     if (httpOrigin == null) httpOrigin = "*"; 
     HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", httpOrigin); 
     HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); 
     HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Token"); 
     HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true"); 

     if (Request.HttpMethod == "OPTIONS") 
     { 
      HttpContext.Current.Response.StatusCode = 200; 
      var httpApplication = sender as HttpApplication; 
      httpApplication.CompleteRequest(); 
     } 
    } 

httpOrigin實際上在允許的主機列表中查找,但這只是複雜的事情。這意味着所有其他請求都被驗證,但選項只是返回。對於這個問題,我就已經丟失

由於沒有它!

+1

我已經嘗試了很多不同的方式來啓用CORS,並在IIS上爲Angular 2客戶端運行WebAPI,包括將其添加到web.config,我的控制器操作上的數據註釋以及在WebApiConfig.Register中調用'EnableCors'。這個解決方案是**只有一個**,它實際上與Windows身份驗證(NTLM)一起工作,同時確保Angular 2 http客戶端在HTTP標頭中發送'withCredentials'。謝謝! –

+0

這真是太棒了!奇蹟般有效!你甚至不必把它放在Application_BeginRequest中。如果只是您想要允許的單個頁面,您甚至可以將其放入頁面加載中。 – Shiroy

0

(與AngularJS或JQuery的工作時)什麼工作對我來說是withCredentials補充:真到每個請求的客戶端:

$http.get("http://localhost:88/api/tests", {withCredentials :true}) 

和啓用服務器上CORS,這與Microsoft.Owin.Cors做從的NuGet並將其添加在啓動象下面這樣:

public void Configuration(IAppBuilder app) 
    { 
     HttpConfiguration config = new HttpConfiguration(); 

     ConfigureOAuth(app); 

     WebApiConfig.Register(config); 
     app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); 
     app.UseWebApi(config); 

    } 

參考文獻:服務器

4

解決這個問題的最簡單的方法是創建條件REQUEST_METHOD =^$ OPTIONS重寫規則。然後將該操作設置爲自定義響應,將其設置爲200 OK。然後,所有選項請求將以200而不是401來響應。這將解決CORS問題。

當然,你還需要確保你有正確的跨起源請求頭。

當啓用集成身份驗證時,這將停止選項請求(其中沒有任何憑據)與401響應。

+0

您是否發現了這個潛在的安全問題? –

1

接受的答案是正確的,但是我是用故障排除設置一個「與iisnode和NPM CORS模塊節點」一會兒一個REST API和不舒服只有啓用匿名身份驗證的所有用戶。由於它是一個節點應用程序,system.web標記沒有多大作用。我結束了以下除了web.config中:

<system.webServer> 
<security> 
    <requestFiltering> 
    <hiddenSegments> 
     <add segment="node_modules" /> 
    </hiddenSegments> 
    </requestFiltering> 
    <authorization> 
    <add accessType="Allow" verbs="OPTIONS" users="?" /> 
    <add accessType="Deny" verbs="GET, PUT, POST, DELETE" users="?" /> 
    </authorization> 
</security> 
</system.webServer> 
0

在WebApiConfig.cs上EnableCorsAttribute啓用SupportCredentials的伎倆對我來說:

public static void Register(HttpConfiguration config) 
{   
    //enable cors request just from localhost:15136 
    var cors = new EnableCorsAttribute("http://localhost:15136", "*", "*"); 
    cors.SupportsCredentials = true; 
    config.EnableCors(cors); 

    //other stuff 
} 

https://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

,請務必發送從javascript調用憑據時({withCredentials :true}

+0

我正在嘗試但沒有憑據。即使使用匿名身份驗證,也沒有運氣 – jpfreire

0

我使用的Web API和OWIN,我試過每個建議如此但唯一有效的工作如下

//use it in your startup class 
app.Use((context, next) => 
{ 
    if (context.Request.Headers.Any(k => k.Key.Contains("Origin")) && context.Request.Method == "OPTIONS") 
    { 
     context.Response.StatusCode = 200; 
     context.Response.Headers.Add("Access-Control-Allow-Origin", new string[1] { "ALLOWED_ORIGIN" }); 
     context.Response.Headers.Add("Access-Control-Allow-Headers", new string[4] { "Origin", "X-Requested-With", "Content-Type", "Accept" }); 
     context.Response.Headers.Add("Access-Control-Allow-Methods", new string[5] { "GET", "POST", "PUT", "DELETE", "OPTIONS" }); 
     context.Response.Headers.Add("Access-Control-Allow-Credentials", new string[1] { "true" }); 

     return context.Response.WriteAsync(""); 
    } 

    return next.Invoke(); 
}); 

//this is important! Without it, it didn't work (probably because the middleware was too late) 
app.UseStageMarker(PipelineStage.Authenticate); 

你需要在你的一個OWIN啓動類的某個地方插入這段代碼。 調用app.UseStageMarker(PipelineStage.Authenticate)是非常重要的,因爲否則預檢檢查失敗。 UseStageMarker的更多信息 - >https://docs.microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline

您需要明確定義允許的標題也很重要。如果您使用*作爲佔位符,它將會失敗。

也許它有助於某人。