2012-10-31 13 views
11

Theo MSDN, khi thuộc tính HttpWebRequest.AllowAutoRedirect là đúng, chuyển hướng sẽ xóa tiêu đề xác thực. Cách giải quyết nhất định là triển khai IAuthenticationModule để xử lý xác thực:Làm cách nào để xử lý xác thực bằng HttpWebRequest.AllowAutoRedirect?

Tiêu đề ủy quyền sẽ bị xóa trên tự động chuyển hướng và HttpWebRequest tự động cố gắng xác thực lại vị trí được chuyển hướng. Trong thực tế, điều này có nghĩa là ứng dụng không thể đặt thông tin xác thực tùy chỉnh vào tiêu đề Cấp quyền nếu có thể gặp phải chuyển hướng. Thay vào đó, ứng dụng phải triển khai và đăng ký một mô-đun xác thực tùy chỉnh. Các System.Net.AuthenticationManager và lớp liên quan được sử dụng để thực hiện một mô-đun xác thực tùy chỉnh. Phương thức AuthenticationManager.Register đăng ký một mô-đun xác thực tùy chỉnh.

Tôi tạo ra một thực hiện cơ bản của giao diện này:

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)))))); 
    } 
} 

và một trình điều khiển đơn giản để thực hiện các chức năng:

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(); 
    } 
} 

Khi tôi thực hiện một yêu cầu mà không chuyển hướng, thì Phương thức Authenticate trên lớp của tôi được gọi và xác thực thành công. Khi tôi thực hiện một yêu cầu mà reutrns một 307 (tạm thời chuyển hướng) phản ứng, không có phương pháp của lớp học của tôi được gọi là, và xác thực không thành công. Những gì đang xảy ra ở đây?

Tôi không muốn tắt tự động chuyển hướng và viết logic tùy chỉnh để tự xử lý các phản hồi 3xx. Làm thế nào tôi có thể nhận được logic xác thực của tôi để làm việc với chuyển hướng tự động?

+0

bạn có thể thử điều này khi bạn thiết lập các keepalive trên đúng thay vì sai? Hoặc đặt URL chuyển hướng trong dòng yêu cầu? Không biết nhiều về điều này nhưng có lẽ nó sẽ giúp –

+0

FWIW, tôi có chính xác cùng một vấn đề và tìm kiếm một giải pháp. – tomo

Trả lời

-2

Điều bạn cần làm có thể là yêu cầu POST. Bạn đang đăng các biến để xác thực, do đó bạn cần sử dụng hành động POST.

Xem bài này để biết thêm thông tin: Login to website, via C#

Auto chuyển hướng không nên trong cách bài yêu cầu này. Tôi khuyên bạn nên cài đặt Fiddler và đăng nhập theo cách thủ công, sau đó xem điều gì xảy ra.

* Lưu ý rằng khi gửi yêu cầu POST, nếu có biểu mẫu đăng nhập, bạn sẽ gửi yêu cầu POST tới thẻ action='/some-url-or-whatever.php' trong biểu mẫu. POST dữ liệu đó và bạn sẽ có thể đăng nhập tốt.

Hãy cho tôi biết nếu điều này có ích.

+0

Câu trả lời này không liên quan đến câu hỏi. Câu hỏi cụ thể hỏi về tiêu đề xác thực bị xóa trong khi chuyển hướng. –

4

Thay cho NetworkCredential, bạn nên chuyển CredentialCache cho request.Credentials.

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

Theo tài liệu MSDN:

Các CredentialCache cửa hàng đẳng cấp thông tin cho nhiều Internet nguồn lực. Các ứng dụng cần truy cập nhiều tài nguyên có thể lưu trữ thông tin xác thực cho các tài nguyên đó trong phiên bản CredentialCache sau đó cung cấp bộ thông tin xác thực phù hợp cho tài nguyên Internet khi được yêu cầu.Khi phương thức GetCredential được gọi là , nó so sánh Mã định danh tài nguyên đồng nhất (URI) và loại xác thực được cung cấp với loại được lưu trữ trong bộ nhớ cache và trả về bộ thông tin xác thực đầu tiên phù hợp.

0

Tôi hy vọng sau đây sẽ là một lựa chọn mà tôi mất từ ​​url dự án mã 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

Mặc dù OP là rất cũ, tôi sẽ đề cử ứng Crater như câu trả lời. Tôi đã đi qua các vòng quay tương tự, bao gồm việc tạo ra một mô-đun xác thực tùy chỉnh mặc dù tài nguyên web tôi đã truy cập chỉ được sử dụng xác thực cơ bản. Những gì tôi thấy là chỉ sau khi tôi sử dụng một CredentialCache, thay vì một NetworkCredential đơn giản, mô-đun xác thực của tôi có được gọi sau khi chuyển hướng không. Hơn nữa, tôi thấy rằng vì xác thực tôi cần là Basic, bằng cách chỉ cung cấp CredentialCache, tôi không cần mô-đun xác thực tùy chỉnh chút nào - mô-đun cơ bản tiêu chuẩn chỉ hoạt động tốt.

Tài nguyên sau dường như xác nhận điều này (ngược lại với tài liệu tham khảo tài liệu .NET được đề cập trong OP):

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

+0

Khi thử nghiệm và mã hóa thêm, có vẻ như đối với một số chuyển hướng nhất định, chỉ cần cung cấp CredentialCache là không đủ. Ví dụ: nếu chuyển hướng chuyển đến một cổng khác, có vẻ như mô-đun xác thực cơ bản tích hợp không xác thực. Nếu bạn cần phải làm theo một cổng khác, thì vẫn cần một mô-đun tùy chỉnh. Như trước đây, bạn phải cung cấp một CredentialCache cho mã của bạn để được gọi là ở tất cả. – tomo