2012-10-31 66 views
11

根據MSDN,當HttpWebRequest.AllowAutoRedirect屬性爲true時,重定向將清除驗證標頭。給出的解決方法是實施IAuthenticationModule辦理身份驗證:如何處理HttpWebRequest.AllowAutoRedirect的認證?

的授權頭在自動重定向清除,HttpWebRequest的自動嘗試重新進行身份驗證,以重定向的位置。實際上,這意味着如果應用程序可能遇到重定向,則無法將自定義身份驗證信息放入授權標頭。相反,應用程序必須實現並註冊一個自定義驗證模塊。 System.Net.AuthenticationManager和相關類用於實現自定義驗證模塊。 AuthenticationManager.Register方法註冊一個自定義認證模塊。

我創造了這個接口的基本實現:

public class CustomBasic : IAuthenticationModule 
{ 
    public CustomBasic() { } 

    public string AuthenticationType { get { return "Basic"; } } 

    public bool CanPreAuthenticate { get { return true; } } 

    private bool checkChallenge(string challenge, string domain) 
    { 
     if (challenge.IndexOf("Basic", StringComparison.InvariantCultureIgnoreCase) == -1) { return false; } 
     if (!string.IsNullOrEmpty(domain) && challenge.IndexOf(domain, StringComparison.InvariantCultureIgnoreCase) == -1) { return false; } 
     return true; 
    } 

    public Authorization PreAuthenticate(WebRequest request, ICredentials credentials) 
    { 
     return authenticate(request, credentials); 
    } 

    public Authorization Authenticate(String challenge, WebRequest request, ICredentials credentials) 
    { 
     if (!checkChallenge(challenge, string.Empty)) { return null; } 
     return this.authenticate(request, credentials); 
    } 

    private Authorization authenticate(WebRequest webRequest, ICredentials credentials) 
    { 
     NetworkCredential requestCredentials = credentials.GetCredential(webRequest.RequestUri, this.AuthenticationType); 
     return (new Authorization(string.Format("{0} {1}", this.AuthenticationType, Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", requestCredentials.UserName, requestCredentials.Password)))))); 
    } 
} 

和一個簡單的驅動程序行使功能:

public class Program 
{ 
    static void Main(string[] args) 
    { 
     // replaces the existing handler for Basic authentication 
     AuthenticationManager.Register(new CustomBasic()); 
     // make a request that requires authentication 
     HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"https://www.SomeUrlThatRequiresAuthentication.com"); 
     request.Method = "GET"; 
     request.KeepAlive = false; 
     request.ContentType = "text/plain"; 
     request.AllowAutoRedirect = true; 
     request.Credentials = new NetworkCredential("userName", "password"); 
     HttpWebResponse result = (HttpWebResponse)request.GetResponse(); 
    } 
} 

當我做不重定向的請求我的班級上的Authenticate方法被調用,並且驗證成功。當我發出請求重新生成307(臨時重定向)響應時,我的類的任何方法都不會被調用,並且認證失敗。這裏發生了什麼?

我寧願不禁用自動重定向並編寫自定義邏輯來自己處理3xx響應。我怎樣才能讓我的身份驗證邏輯與自動重定向一起工作?

+0

你可以試試這個?或者將重定向網址放在請求行中?對此不太瞭解,但也許有幫助 –

+0

FWIW,我有完全相同的問題並尋找解決方案。 – tomo

回答

-2

你需要做的可能是POST請求。您正在發佈要驗證的變量,因此您需要使用POST操作。

看到這個職位的詳細資料:Login to website, via C#

自動重定向不應該在這個崗位要求的方式獲得。我建議安裝Fiddler並手動登錄,然後觀察會發生什麼。 *請注意,發送POST請求時,如果有登錄表單,您需要將POST請求發送至表單中的action='/some-url-or-whatever.php'標籤。請注意,發送POST請求時,如果有登錄表單,請發送POST請求至表單中的action='/some-url-or-whatever.php'標籤。 POST這個數據,你應該能夠很好地登錄。

讓我知道這是否有幫助。

+0

這個答案與問題無關。該問題具體詢問在重定向過程中驗證標頭是否被清除。 –

4

代替NetworkCredential,您應該爲request.Credentials傳遞一個CredentialCache。

CredentialCache cache = new CredentialCache(); 
cache.Add(new Uri(@"https://www.SomeUrlThatRequiresAuthentication.com", "Basic", new NetworkCredential("username", "password")); 
request.Credentials = cache; 

根據MSDN文檔:

的CredentialCache爲多個互聯網 資源類存儲憑證。需要訪問多個資源的應用程序 可將這些資源的憑證存儲在CredentialCache 實例中,該實例隨後會在需要時向 Internet資源提供適當的憑據集。當調用GetCredential方法爲 時,它比較統一資源標識符(URI)和 認證類型,這些認證類型與存儲在緩存中的認證類型進行比較,並返回匹配的第一組認證信息。

0

我希望下面是我從代碼項目網址http://www.codeproject.com/Articles/49243/Handling-Cookies-with-Redirects-and-HttpWebRequest

String targetUrl = "https://www.SomeUrlThatRequiresAuthentication.com"; 

    HttpWebRequest request = GetNewRequest(targetUrl); 
    HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 

    while (response.StatusCode == HttpStatusCode.MovedPermanently) 
    { 
     response.Close(); 
     request = GetNewRequest(response.Headers["Location"]); 
     response = (HttpWebResponse)request.GetResponse(); 
    } 


private static HttpWebRequest GetNewRequest(string targetUrl) 
{ 

    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(targetUrl); 
    request.AllowAutoRedirect = false; 
    request.Headers.Add("Authorization", "Basic xxxxxxxx"); 
    return request; 
} 
0

即使OP是很老了另一種選擇,我將提名隕石坑的答案迴應。我經歷了類似的旋轉,包括創建自定義身份驗證模塊,即使我只訪問使用的基本身份驗證的Web資源。我發現只有在我使用了CredentialCache而不是簡單的NetworkCredential之後,我的身份驗證模塊在重定向後才被調用。

此外,我發現由於我需要的身份驗證是Basic,只需提供CredentialCache,我根本不需要自定義身份驗證模塊 - 標準的基本模塊工作得很好。

下的資源似乎證實了這一點(相對於在OP中提到的.NET文檔參考):當您設置到keepAlive上真正的而不是虛假

https://blogs.msdn.microsoft.com/ncl/2009/05/05/custom-http-authentication-schemes/

+0

在進一步的測試和編碼上,似乎對於某些重定向,只提供CredentialCache是​​不夠的。例如,如果重定向轉到另一個端口,看起來內置的基本認證模塊無法進行認證。如果您需要關注另一個端口,那麼仍然需要自定義模塊。和以前一樣,你必須提供一個CredentialCache來完成你的代碼的調用。 – tomo