Как объект "WebRequest" определяет реализацию "IAuthenticationModule" для использования? - PullRequest
0 голосов
/ 03 мая 2019

Я хотел бы использовать класс AuthenticationManager System.Net для определения основного или авторизационного заголовка для WebRequest .

.

AuthenticationManager предоставляет метод Register для добавления нового модуля (реализация IAuthenticationModule ). Это говорит о том, что можно зарегистрировать несколько модулей и что есть способ выбрать один из этих модулей.

И я полагаю, что выбор модуля должен быть сделан путем предоставления значения, определенного в свойстве «AuthenticationType» модуля. Я определяю его в CredentialCache , который я передаю моему «WebRequest».

Я пытался создать и сохранить 2 модуля:

  • Модуль для переопределения базовой авторизации (чтобы отключить предварительную аутентификацию) (я использую пример документации Microsoft: здесь )
  • Модуль для авторизации на предъявителя.

Затем я сохраняю свои 2 модуля в AuthenticationManager со следующим кодом:

// I remove the previous basic module 
AuthenticationManager.Unregister("Basic");

// And i register my 2 modules
AuthenticationManager.Register(customBasicModule);
AuthenticationManager.Register(customBearerModule);

Но похоже, что это всегда первый модуль записи, который вызывается.

Мой тестовый код:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://example.com");

var cache = new CredentialCache();
cache.Add(new Uri("http://example.com"), "Basic", new NetworkCredential("user", "password"));

request.Method = "GET";    
request.Credentials = cache;

HttpWebResponse response = (HttpWebResponse)request.GetResponse();

Я ожидаю, что будет вызван «customBasicModule», потому что я указал «Basic» в свойстве «AuthenticationType» этого модуля, а также в «CredentialCache». Но если я сначала зарегистрирую «customBearerModule», он будет вызван.

Модули:

public class BasicAuthenticationModule : IAuthenticationModule
{
    private const string BASIC_SCHEME = "Basic";

    public bool CanPreAuthenticate => false;

    public string AuthenticationType => BASIC_SCHEME;

    public Authorization Authenticate(string challenge, WebRequest request, ICredentials credentials)
    {
        // Some code to get Basic from ICredentials
    }

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

public class BearerAuthenticationModule : IAuthenticationModule
{
    private const string BEARER_SCHEME = "Bearer";

    public bool CanPreAuthenticate => false;

    public string AuthenticationType => BEARER_SCHEME;

    public Authorization Authenticate(string challenge, WebRequest request, ICredentials credentials)
    {
        // Some code to get Bearer from ICredentials
    }

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

1 Ответ

0 голосов
/ 06 июня 2019

AuthenticationManager всегда будет вызывать все IAuthenticationModule в порядке их регистрации до тех пор, пока один из них не вернет ненулевой экземпляр авторизации.

Идея состоит в том, что каждая реализация IAuthenticationModule должна проверять параметр вызова на соответствие тому, чем они являются.способен делать и возвращать ноль, если они не совпадают.

Так что ваши реализации должны выглядеть так:

public class BasicAuthenticationModule : IAuthenticationModule
{
    private const string BASIC_SCHEME = "Basic";

    public bool CanPreAuthenticate => false;

    public string AuthenticationType => BASIC_SCHEME;

    public Authorization Authenticate(string challenge, WebRequest request, ICredentials credentials)
    {
        if (!challenge.StartWith(BASIC_SCHEME)) return null;
        // Some code to get Basic from ICredentials
    }

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

public class BearerAuthenticationModule : IAuthenticationModule
{
    private const string BEARER_SCHEME = "Bearer";

    public bool CanPreAuthenticate => false;

    public string AuthenticationType => BEARER_SCHEME;

    public Authorization Authenticate(string challenge, WebRequest request, ICredentials credentials)
    {
        if (!challenge.StartWith(BEARER_SCHEME)) return null;
        // Some code to get Bearer from ICredentials
    }

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

Также обратите внимание, что проблемой является содержимое заголовка WWW-Authenticate, отправленногосервер после первого неавторизованного ответа (401), который не связан с «базовым», который вы записываете в CredentialCache

...