c# - “WebRequest”对象如何确定要使用的“IAuthenticationModule”实现?
问题描述
我想使用 System.Net 的AuthenticationManager类来定义WebRequest的基本或不记名授权标头。
AuthenticationManager 提供了一个 Register 方法来添加一个新模块(IAuthenticationModule的实现)。这表明可以注册多个模块,并且可以选择其中一个模块。
而且我认为必须通过给出在模块的“AuthenticationType”属性中定义的值来完成模块选择。我在传递给我的“WebRequest”的CredentialCache中定义它。
我尝试创建并保存 2 个模块:
- 重新定义基本授权的模块(禁用预认证)(我使用 Microsoft 文档的示例: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,直到返回一个非 null Authorization 实例。
这个想法是每个 IAuthenticationModule 实现都应该根据他们能够做什么来验证挑战参数,如果它们不匹配则返回 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 标头的内容,这与您在 CredentialCache 中编写的“基本”无关
推荐阅读
- android - 什么情况下 findViewById 会突然返回 null?
- javascript - 谷歌应用脚本 - 如何从范围内获取单元格对齐
- sql - Null 的参数化查询
- ms-access - 子表单最初不显示过滤结果
- asp.net-mvc - ASP.NET MVC:如何在不久的将来收到有关更新或事件的通知?
- cassandra - 获取在 cassandra 集群中执行的查询列表
- java - Full GC 似乎没有执行(内存不足)
- c# - 如何在 xamarin 表单中使用 zxing 将生成的二维码保存为图像
- java - 检索枚举的注释值
- python - 我如何对数字求和直到最大高度?