Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# HttpWebrequest/WebClient/HttpClient/CookieContainer bug?如果响应Uri不包含cookie,则不添加cookie';s路径_C#_.net_Cookies_Httpwebrequest_Cookiecontainer - Fatal编程技术网

C# HttpWebrequest/WebClient/HttpClient/CookieContainer bug?如果响应Uri不包含cookie,则不添加cookie';s路径

C# HttpWebrequest/WebClient/HttpClient/CookieContainer bug?如果响应Uri不包含cookie,则不添加cookie';s路径,c#,.net,cookies,httpwebrequest,cookiecontainer,C#,.net,Cookies,Httpwebrequest,Cookiecontainer,我试图使用C#(WebClient/HttpWebRequest)登录我的WordPress管理面板 我向/wp login.php发送了一个POST请求。 它会以如下方式响应cookies: Set-Cookie: wordpress_26...cf9e; path=/wordpress/wp-content/plugins; httponly Set-Cookie: wordpress_26...cf9e; path=/wordpress/wp-admin; httponly Set-Coo

我试图使用C#(WebClient/HttpWebRequest)登录我的WordPress管理面板

我向
/wp login.php
发送了一个POST请求。 它会以如下方式响应cookies:

Set-Cookie: wordpress_26...cf9e; path=/wordpress/wp-content/plugins; httponly
Set-Cookie: wordpress_26...cf9e; path=/wordpress/wp-admin; httponly
Set-Cookie: wordpress_logged_in_26...43b3; path=/wordpress/; httponly
它还重定向到
/wp admin/
位置:http://109.120.169.99/wordpress/wp-admin/

问题是第二个cookie(路径为
path=/wp admin
)没有添加到CookieContainer,因此登录失败

我查看了HttpWebRequest源代码和(OnReceiveHeaders),发现它对所有cookie使用
ResponseUri

我尝试使用响应uri手动添加cookie,但得到一个异常,路径无效。之后我找到了这个答案:它说Uri必须与添加到CookieContainer时来自cookie的路径相匹配

我最终禁用了AllowAutoRedict(手动处理)并手动添加这些cookie

这是我的密码:

public static void Auth(string url, string username, string password)
{
    var webClient = new CookieAwareWebClient();

    // load page to get some cookies
    string loginPageHtml = webClient.DownloadString(url);

    webClient.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
    webClient.Headers.Add(HttpRequestHeader.Referer, url);

    var postValues = new NameValueCollection()
        {
            {"log", username},
            {"pwd", password},
            {"wp-sumbit", "Log In"},
            {"redirect_to", url.Replace("wp-login.php", "wp-admin/") },
            {"testcookie", "1"}
        };

    webClient.AllowRedirects = false; // to handle cookies and redirect manually

    byte[] response = webClient.UploadValues(url, postValues);
    string html = Encoding.UTF8.GetString(response);

    // <FIX>, handle cookies and redirect manually

    string cookies = webClient.ResponseHeaders[HttpResponseHeader.SetCookie];
    var cookiesArr = cookies.Split(',');

    foreach (var cookieStr in cookiesArr)
    {
        var parts = cookieStr.Split(';').Select(s => s.Trim());

        foreach (var part in parts)
        {
            if (part.Contains("path="))
            {
                string path = part.Replace("path=", "");

                var uri = new Uri(url);

                if (path != "/" && !uri.LocalPath.Contains(path))
                {
                    var uriBuilder = new UriBuilder(uri.Scheme, uri.Host, 80,
                        path);

                    webClient.CookieContainer.SetCookies(uriBuilder.Uri, cookieStr);
                }
            }
        }
    }
    // </FIX>

    while (webClient.StatusCode() == HttpStatusCode.Redirect)
    {
        string redirectUrl = webClient.ResponseHeaders[HttpResponseHeader.Location];

        html = webClient.DownloadString(redirectUrl);
    }

    if (html.Contains("?action=logout"))
        Console.WriteLine("Login success");
    else
        Console.WriteLine("Login fail");
}
我还尝试使用.NET 4.5 HttpClient,但结果相同(我认为它也在下面使用HttpWebRequest):

publicstaticvoidauth2(字符串url、字符串用户名、字符串密码)
{
使用(var httpClient=new httpClient())
{
var loginPageHtml=httpClient.GetStringAsync(url).Result;
var postContent=新列表()
{
新的KeyValuePair(“日志”,用户名),
新的KeyValuePair(“pwd”,密码),
新的KeyValuePair(“wp提交”、“登录”),
新的KeyValuePair(“重定向到”),url.Replace(“wp login.php”,“wp admin/”),
新的KeyValuePair(“testcookie”,“1”)
};
var response=httpClient.PostAsync(url,新FormUrlEncodedContent(postContent)).Result;
字符串html=response.Content.ReadAsStringAsync().Result;
if(html.Contains(“?action=logout”))
Console.WriteLine(“登录成功”);
其他的
Console.WriteLine(“登录失败”);
}
}
我是做错了什么,还是HttpWebRequest/CookieContainer中有一个bug

下面是完整的源代码,如果有人想测试它,可以很方便地使用:(我的测试网站和登录/密码也可以)

和Fiddler日志:

  • -webbrowser(Chrome),它添加了这个cookie
  • -网络客户
  • - HttpClient
// WebClient with CookieContainer
public class CookieAwareWebClient : WebClient
{
    private WebRequest _request = null;
    private WebResponse _response = null;

    public CookieContainer CookieContainer { get; private set; }

    public string UserAgent { get; set; }

    public bool AllowRedirects { get; set; }

    public CookieAwareWebClient()
    {
        UserAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36";
        CookieContainer = new CookieContainer();
        AllowRedirects = true;
    }

    protected override WebRequest GetWebRequest(Uri address)
    {
        _request = base.GetWebRequest(address);
        if (_request is HttpWebRequest)
        {
            var httpRequest = (HttpWebRequest)_request;
            httpRequest.CookieContainer = CookieContainer;
            httpRequest.UserAgent = UserAgent;

            httpRequest.AllowAutoRedirect = AllowRedirects;

            httpRequest.ProtocolVersion = HttpVersion.Version11;

            httpRequest.Timeout = 50000;
        }
        return _request;
    }

    protected override WebResponse GetWebResponse(WebRequest request)
    {
        _response = base.GetWebResponse(request);

        return _response;
    }

    // Returns status code of the last response
    public HttpStatusCode StatusCode()
    {
        var httpResponse = _response as HttpWebResponse;

        if (httpResponse == null)
            throw new InvalidOperationException("Unable to retrieve the status code, maybe you have not made a request yet.");

        var result = httpResponse.StatusCode;

        return result;
    }
}
public static void Auth2(string url, string username, string password)
{
    using (var httpClient = new HttpClient())
    {
        var loginPageHtml = httpClient.GetStringAsync(url).Result;

        var postContent = new List<KeyValuePair<string, string>>()
            {
                new KeyValuePair<string, string>("log", username),
                new KeyValuePair<string, string>("pwd", password),
                new KeyValuePair<string, string>("wp-submit", "Log In"),
                new KeyValuePair<string, string>("redirect_to", url.Replace("wp-login.php", "wp-admin/")),
                new KeyValuePair<string, string>("testcookie", "1")
            };

        var response = httpClient.PostAsync(url, new FormUrlEncodedContent(postContent)).Result;

        string html = response.Content.ReadAsStringAsync().Result;

        if (html.Contains("?action=logout"))
            Console.WriteLine("Login success");
        else
            Console.WriteLine("Login fail");
    }
}