В соответствии с MSDN, когда свойство HttpWebRequest.AllowAutoRedirect
равно true, перенаправления очистят заголовки аутентификации. Обходным путем является реализация IAuthenticationModule для проверки подлинности:
Заголовок авторизации очищается при автопереадресации, и 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. Как я могу заставить свою логику аутентификации работать с автопереадресацией?