2013-08-29 76 views
4

我試圖在一個現有的asp.net網站上啓用CORS,該網站承載了幾個WCF服務。不幸的是,我正在努力工作。乍一看,我被重定向到登錄頁面(不存在),所以可能是由自定義身份驗證服務生成的身份驗證cookie有問題。CORS:訪問需要身份驗證的Web服務

繼續之前,這裏是我當前場景的簡單描述:

  • 我有站點A,暴露多個Web服務(所有,但 認證服務只能通過身份驗證的用戶訪問), 和網站B,它有一個頁面,試圖與網絡互動 服務
  • 爲了複製這種情況下,我已經把 服務+ html頁面放在同一個地方,我已經創建一個別名 (hosts文件),以模擬cors調用(比方說,我 稱之爲outro.pt)
  • 通過使用 的FormsAuthentication.GetAuthCookie產生的驗證cookie,然後它通過調用Response.AppendCookie方法
  • 認證工作正常添加到 響應:首先有一個OPTIONS呼叫,然後是POST 呼叫;當第二個Web服務被調用(POST再次)時,沒有 預檢檢查(因爲第一次調用結束生成一個 訪問控制最大年齡標頭爲了緩存預檢檢查爲 5分鐘),但網絡網站(outro.pt)最終返回302,其中 將瀏覽器重定向到登錄頁面。

    繼續之前,這裏是用於處理預檢,並允許CORS電話(我把它放在應用程序的BeginRequest事件中)的演示代碼:

    private void Application_BeginRequest(object sender, EventArgs e) { 
        var ctx = HttpContext.Current; 
    
        //allow credentials: always 
        ctx.Response.AddHeader("Access-Control-Allow-Credentials", "true"); 
    
        //add allow origin header 
        if (ctx.Request.Headers["Origin"] != null) { 
         ctx.Response.AddHeader("Access-Control-Allow-Origin", ctx.Request.Headers["Origin"]); 
        } 
    
        if (ctx.Request.Headers["Access-Control-Request-Headers"] != null) { 
         ctx.Response.AddHeader("Access-Control-Allow-Headers", ctx.Request.Headers["Access-Control-Request-Headers"]); 
        } 
    
        if (ctx.Request.HttpMethod.ToUpper() == "OPTIONS") { 
         ctx.Response.AddHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS"); 
         //keep preflight info for 5 mins 
         ctx.Response.AddHeader("Access-Control-Max-Age", (5 * 60).ToString()); 
         ctx.Response.End(); 
         return; 
        } 
    } 
    

現在,這裏的演示代碼生成身份驗證Cookie(因爲這是演示代碼,我已經選擇了使用簡單的通用處理器爲它:

public void ProcessRequest(HttpContext context) { 
     context.Response.ContentType = "application/json"; 
     var name = ""; 
     using (var reader = new StreamReader(context.Request.InputStream)) { 
      var std = (Student)JsonConvert.DeserializeObject(reader.ReadToEnd(),typeof(Student)); 
      name = std == null ? "" : std.name; 
     } 
     if (!String.IsNullOrEmpty(name)) { 
      var cookie = FormsAuthentication.GetAuthCookie(name, false);    
      cookie.Domain = "outro.pt"; 
      context.Response.AppendCookie(cookie); 
      context.Response.Write(JsonConvert.SerializeObject(new {valid = true})); 
     } 
     else { 
      context.Response.Write(JsonConvert.SerializeObject(new { valid = false }));  
     } 

    } 

現在,使用招後,我可以看到,該cookie被弄回來的時候驗證處理程序被調用。舉例來說,這裏是通過調用創建到先前的認證處理一個的cookie的例子:

的Set-Cookie:.ASPXAUTH = 1CB7EF39DBA39BDA2FD2AA0A0AAFDAB67821A286D04F1678C89CFD6036094A3F9C36D2C9E48FFE35B95C8A742F553138A8899E2CE63259F6DDC7A4D59868AF8A3F50EC037F1DAB73827B5D906A115C28FC8E4B744D661AF77592955F525E236D;域= outro.pt;路徑= /; HttpOnly

乍一看,我無法看到這個身份驗證cookie沒有任何問題(我認爲它與正確的域相關聯,每當我打開任何頁面在outro.pt內時都應該發送它,對嗎?它被放置在另一個asp.net應用程序中,比如outro.pt/demo/webservice.ashx?)

由於我在嘗試訪問第二個Web服務時被重定向到登錄頁面,問題在於驗證Cookie未被髮送。這是正確的:根據fiddler,第二次調用的請求標頭中沒有發送cookie。我嘗試了幾件事,但我無法設法使其工作。

閱讀文檔後,我認爲將withCredentials字段設置爲true是我發送cookie所需的唯一必需事項,對吧?順便說一句,這裏的是通過使用jquery2進行第二次Web服務調用:

var complete = url + "studentservice.ashx"; 
    payload = { 
        url: complete, 
        type: 'POST', 
        xhrFields: { 
         withCredentials: true 
        }, 
        contentType: 'application/json', 
        crossDomain: true, 
        dataType: 'json' 
       }; 
    $.ajax(payload) 
        .done(function (data, status, xhr) { 
         alert("success"); 

        }) 
        .fail(function (xhr, status, error) { 
         alert("error" + error); 
        }); 

那麼,有沒有人管理時需要訪問的Web服務要求asp.net身份驗證使用CORS?我錯過了什麼?

謝謝。

回答

1

我想我發現了這個問題:驗證用戶(並生成cookie)的$ .ajax方法調用沒有withCredentials字段,所以從服務器返回的cookie最終被丟棄。

+0

謝謝。我有類似的問題。你能多解釋一下嗎?什麼方法調用沒有通過withCredentials字段>? –

+0

當然。如果我沒有弄錯,你需要將xhrFields對象添加到執行用戶驗證和認證的$ ajax調用中。僅在後續請求中使用它(即驗證後執行的請求)將不起作用。 –

+0

好的,謝謝你。我認爲這就是你的意思。 –