12

根据MSDN,当HttpWebRequest.AllowAutoRedirect属性为 true 时,重定向将清除身份验证标头。给出的解决方法是实现 IAuthenticationModule 来处理身份验证:

Authorization 标头在自动重定向时被清除,并且 HttpWebRequest 自动尝试重新验证到重定向的位置。实际上,这意味着如果可能遇到重定向,应用程序不能将自定义身份验证信息放入 Authorization 标头中。相反,应用程序必须实现并注册一个自定义身份验证模块。System.Net.AuthenticationManager 和相关类用于实现自定义身份验证模块。AuthenticationManager.Register 方法注册一个自定义身份验证模块。

我创建了这个接口的基本实现:

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 响应。如何让我的身份验证逻辑与自动重定向一起使用?

4

4 回答 4

6

代替 NetworkCredential,您应该为 request.Credentials 传递 CredentialCache。

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) 和身份验证类型与缓存中存储的进行比较,并返回匹配的第一组凭据。

于 2015-07-10T00:15:13.470 回答
0

我希望以下是我从代码项目 url http://www.codeproject.com/Articles/49243/Handling-Cookies-with-Redirects-and-HttpWebRequest中获取的另一个选项

    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;
}
于 2015-11-10T17:08:49.767 回答
0

即使 OP 已经很老了,我会提名 Crater 的回应作为答案。我经历了类似的变化,包括创建自定义身份验证模块,即使我访问的 Web 资源仅使用基本身份验证。我发现只有在我使用 CredentialCache 而不是简单的 NetworkCredential 之后,我的身份验证模块才会在重定向后被调用。

此外,我发现由于我需要的身份验证是 Basic,因此仅提供 CredentialCache 我根本不需要自定义身份验证模块——标准的 Basic 模块工作得很好。

以下资源似乎证实了这一点(与 OP 中提到的 .NET 文档参考相反):

https://blogs.msdn.microsoft.com/ncl/2009/05/05/custom-http-authentication-schemes/

于 2016-09-19T13:21:58.963 回答
-3

您需要做的可能是一个POST请求。您正在发布变量以进行身份​​验证,因此您需要使用该POST操作。

有关更多信息,请参阅此帖子:通过 C# 登录网站

自动重定向不应妨碍此发布请求。我建议安装 Fiddler 并手动登录,然后观察会发生什么。

*请记住,发送POST请求时,如果有登录表单,则您将POST请求发送到action='/some-url-or-whatever.php'表单中的标签。POST数据到那个,你应该可以登录就好了。

让我知道这是否有帮助。

于 2015-06-16T19:09:30.673 回答