C# 如何使用HttpWebRequest.AllowAutoRedirect处理身份验证?
根据,当HttpWebRequest.AllowAutoRedirect属性为true时,重定向将清除身份验证头。给出的解决方法是实现IAAuthenticationModule来处理身份验证: 自动重定向时会清除授权标头,HttpWebRequest会自动尝试重新验证重定向位置。实际上,这意味着如果可能遇到重定向,应用程序无法将自定义身份验证信息放入授权头中。相反,应用程序必须实现并注册自定义身份验证模块。System.Net.AuthenticationManager和相关类用于实现自定义身份验证模块。AuthenticationManager.Register方法注册自定义身份验证模块 我创建了此接口的基本实现:C# 如何使用HttpWebRequest.AllowAutoRedirect处理身份验证?,c#,http,authentication,redirect,C#,Http,Authentication,Redirect,根据,当HttpWebRequest.AllowAutoRedirect属性为true时,重定向将清除身份验证头。给出的解决方法是实现IAAuthenticationModule来处理身份验证: 自动重定向时会清除授权标头,HttpWebRequest会自动尝试重新验证重定向位置。实际上,这意味着如果可能遇到重定向,应用程序无法将自定义身份验证信息放入授权头中。相反,应用程序必须实现并注册自定义身份验证模块。System.Net.AuthenticationManager和相关类用于实现自定义身
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响应。如何使身份验证逻辑与自动重定向一起工作?您需要做的可能是一个
POST
请求。您正在发布变量以进行身份验证,因此需要使用POST
操作
有关更多信息,请参阅本文:
自动重定向不应妨碍此post请求。我建议安装Fiddler并手动登录,然后观察发生了什么
*请记住,在发送POST
请求时,如果有登录表单,则将POST
请求发送到表单中的action='/some url或任何.php'
标记POST
将数据发送到该页面,您应该可以很好地登录
如果有帮助,请告诉我。您应该传递request.Credentials的CredentialCache来代替NetworkCredential
CredentialCache cache = new CredentialCache();
cache.Add(new Uri(@"https://www.SomeUrlThatRequiresAuthentication.com", "Basic", new NetworkCredential("username", "password"));
request.Credentials = cache;
根据MSDN文件:
CredentialCache类存储多个Internet服务器的凭据
资源。需要访问多个资源的应用程序可以
将这些资源的凭据存储在CredentialCache中
实例,然后向
需要时提供Internet资源。当使用GetCredential方法时
调用时,它比较统一资源标识符(URI)和
与存储在缓存中的身份验证一起提供的身份验证类型,以及
返回匹配的第一组凭据
我希望下面是我从代码项目url中选择的另一个选项
尽管OP已经很老了,但我还是会提名陨石坑的反应作为答案。我经历了类似的循环,包括创建自定义身份验证模块,尽管我访问的web资源只使用基本身份验证。我发现,只有在使用CredentialCache而不是简单的NetworkCredential之后,我的身份验证模块才在重定向后被调用 此外,我发现由于我需要的身份验证是基本的,因此仅提供CredentialCache,我根本不需要自定义身份验证模块——标准的基本模块工作得很好 以下资源似乎证实了这一点(与OP中提到的.NET文档参考相比):
当您将keepAlive设置为true而不是false时,是否可以尝试此操作?或者将重定向URL放在请求行中?我对此不太了解,但可能会有所帮助。我也遇到了同样的问题,正在寻找解决方案。这个答案与问题无关。这个问题特别询问在重定向过程中是否清除了身份验证头。在进一步的测试和编码中,似乎对于某些重定向来说,仅仅提供一个CredentialCache是不够的。例如,如果重定向到其他端口,则内置基本身份验证模块似乎无法进行身份验证。如果需要转到另一个端口,则仍然需要自定义模块。和以前一样,您必须提供一个CredentialCache才能调用代码。
String targetUrl = "https://www.SomeUrlThatRequiresAuthentication.com";
HttpWebRequest request = GetNewRequest(targetUrl);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
while (response.StatusCode == HttpStatusCode.MovedPermanently)
{
response.Close();
request = GetNewRequest(response.Headers["Location"]);
response = (HttpWebResponse)request.GetResponse();
}
private static HttpWebRequest GetNewRequest(string targetUrl)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(targetUrl);
request.AllowAutoRedirect = false;
request.Headers.Add("Authorization", "Basic xxxxxxxx");
return request;
}