简体   繁体   English

“ WebRequest”对象如何确定要使用的“ IAuthenticationModule”实现?

[英]How “WebRequest” object determine the “IAuthenticationModule” implementation to use?

I would like to use System.Net's AuthenticationManager class to define the basic or bearer authorization header of a WebRequest . 我想使用System.Net的AuthenticationManager类来定义WebRequest的基本或承载授权标头。

AuthenticationManager provides a Register method to add a new module (implementation of IAuthenticationModule ). AuthenticationManager提供了Register方法来添加新模块( IAuthenticationModule的实现)。 This suggests that it is possible to register multiple modules and that there is a way to select one of these modules. 这表明可以注册多个模块,并且可以选择其中一个模块。

And I suppose that module selection must be done by giving the value that is defined in the "AuthenticationType" property of the module. 而且我认为必须通过提供模块“ AuthenticationType”属性中定义的值来完成模块选择。 I define it in a CredentialCache that I pass to my "WebRequest". 我在传递给“ WebRequest”的CredentialCache中定义它。

I tried to create and save 2 modules: 我尝试创建并保存2个模块:

  • A module to redefine the basic authorization (to disable the pre-authentication) (I use the example of the Microsoft documentation: here ) 重新定义基本授权(以禁用预身份验证)的模块(我使用Microsoft文档的示例: 此处
  • A module for authorization bearer. 授权载体模块。

Then I save my 2 modules in AuthenticationManager with the following code: 然后,使用以下代码将2个模块保存在AuthenticationManager中:

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

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

But it seems that this is always the first record module that is called. 但这似乎总是第一个被调用的记录模块。

My test code: 我的测试代码:

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

I expect the "customBasicModule" to be called because I indicated "Basic" in the property "AuthenticationType" of this module and also in the "CredentialCache". 我希望调用“ customBasicModule”,因为我在此模块的属性“ AuthenticationType”和“ CredentialCache”中都指示了“ Basic”。 But if I register the "customBearerModule" first, it will be called. 但是,如果我先注册“ customBearerModule”,它将被调用。

Modules : 模块:

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

The AuthenticationManager will always call all IAuthenticationModule in the order they have been register until one return a non null Authorization instance. AuthenticationManager将始终按照注册时的顺序调用所有IAuthenticationModule,直到一个返回非null授权实例为止。

The idea is that each IAuthenticationModule implementation is expected to validate the challenge parameter against what they are able to do and return null if they do not match. 想法是,每个IAuthenticationModule实现都应根据其能力验证质询参数,如果不匹配,则返回null。

So your implementations should looks to 所以您的实现应该看起来像

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

Also pay attention that the challenge is the content of the WWW-Authenticate header send by the server after a first unauthorized response (401) which is not related to the "basic" that you write in the CredentialCache 还请注意,挑战是服务器在第一个未经授权的响应(401)之后由服务器发送的WWW-Authenticate标头的内容,该响应与您在CredentialCache中编写的“基本”无关

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM