"WebRequest" 对象如何确定要使用的 "IAuthenticationModule" 实现?
How "WebRequest" object determine the "IAuthenticationModule" implementation to use?
我想使用 System.Net 的 AuthenticationManager class to define the basic or bearer authorization header of a WebRequest。
AuthenticationManager 提供了一个 Register 方法来添加一个新模块(IAuthenticationModule 的实现)。这表明可以注册多个模块,并且有一种方法可以 select 其中一个模块。
而且我认为模块 selection 必须通过提供在模块的 "AuthenticationType" 属性 中定义的值来完成。我在传递给我的 "WebRequest".
的 CredentialCache 中定义了它
我尝试创建并保存 2 个模块:
- 重新定义基本授权(禁用预认证)的模块(我用微软文档的例子:here)
- 授权承载模块。
然后我使用以下代码将我的 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",因为我在该模块的 属性 "AuthenticationType" 和 "CredentialCache" 中指示了 "Basic"。
但是如果我先注册"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;
}
}
AuthenticationManager 将始终按照注册的顺序调用所有 IAuthenticationModule,直到一个 return 非空授权实例。
这个想法是每个 IAuthenticationModule 实现都应该根据它们能够做什么来验证挑战参数,如果它们不匹配,return null。
所以您的实施应该参考
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;
}
}
另请注意,挑战是服务器在第一次未授权响应(401)后发送的 WWW-Authenticate header 的内容,与 "basic" 无关你写在 CredentialCache
我想使用 System.Net 的 AuthenticationManager class to define the basic or bearer authorization header of a WebRequest。
AuthenticationManager 提供了一个 Register 方法来添加一个新模块(IAuthenticationModule 的实现)。这表明可以注册多个模块,并且有一种方法可以 select 其中一个模块。
而且我认为模块 selection 必须通过提供在模块的 "AuthenticationType" 属性 中定义的值来完成。我在传递给我的 "WebRequest".
的 CredentialCache 中定义了它我尝试创建并保存 2 个模块:
- 重新定义基本授权(禁用预认证)的模块(我用微软文档的例子:here)
- 授权承载模块。
然后我使用以下代码将我的 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",因为我在该模块的 属性 "AuthenticationType" 和 "CredentialCache" 中指示了 "Basic"。 但是如果我先注册"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;
}
}
AuthenticationManager 将始终按照注册的顺序调用所有 IAuthenticationModule,直到一个 return 非空授权实例。
这个想法是每个 IAuthenticationModule 实现都应该根据它们能够做什么来验证挑战参数,如果它们不匹配,return null。
所以您的实施应该参考
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;
}
}
另请注意,挑战是服务器在第一次未授权响应(401)后发送的 WWW-Authenticate header 的内容,与 "basic" 无关你写在 CredentialCache