将cookie从一个WebClient复制到另一个WebClient?

时间:2013-03-04 22:13:24

标签: c# .net webclient parallels

我想知道是否可以将cookie从一个Web客户端复制到另一个Web客户端。

原因

我正在使用并行Web请求,它会在每个新线程上创建新的Web客户端实例。

问题

信息非常敏感,需要使用发布请求进行授权并保存Cookie。所以基本上那些新的Web客户端实例无法访问。我不想授权每个正在创建的Web客户端,所以我想知道是否可以以某种方式将cookie从一个Web客户端复制到另一个Web客户端。

示例代码

public class Scrapper
{
    CookieAwareWebClient _web = new CookieAwareWebClient();

    public Scrapper(string username, string password)
    {
        this.Authorize(username, password); // This sends correct post request and then it sets the cookie on _web
    }

    public string DowloadSomeData(int pages)
    {
        string someInformation = string.Empty;

        Parallel.For(0, pages, i =>
        {
            // Cookie is set on "_web", need to copy it to "web"
            var web = new CookieAwareWebClient(); // No authorization cookie here
            html = web.DownloadString("http://example.com/"); // Can't access this page without cookie

            someInformation += this.GetSomeInformation(html)
        });

        return someInformation;
    }
}

// This is cookie aware web client that I use
class CookieAwareWebClient : WebClient
{
    private CookieContainer cookie = new CookieContainer();

    protected override WebRequest GetWebRequest(Uri address)
    {
        WebRequest request = base.GetWebRequest(address);
        if (request is HttpWebRequest)
        {
            (request as HttpWebRequest).CookieContainer = cookie;
        }
        return request;
    }
}

1 个答案:

答案 0 :(得分:5)

我相信您可以在CookieContainer个对象之间共享WebClient个实例。因此,一旦您进行了身份验证,请为您创建的每个新客户端重复使用相同的CookieContainer。请注意您的后续请求不会修改CookieContainer,否则您可能会遇到竞争条件,因为我怀疑该类对并行修改是线程安全的。

首先,使用可以传入cookie容器的自定义构造函数修改CookieAwareWebClient。另外,提供一种通过属性获取容器引用的方法:

class CookieAwareWebClient : WebClient
{
    private CookieContainer cookie;

    public CookieContainer Cookie { get { return cookie; } }

    public CookieAwareWebClient() {
        cookie = new CookieContainer();
    }

    public CookieAwareWebClient(CookieContainer givenContainer) {
        cookie = givenContainer;
    }
}

然后,您的Scrapper类应在身份验证后将自己的CookieContainer传递给每个客户端:

public string DowloadSomeData(int pages)
{
    string someInformation = string.Empty;
    CookieContainer cookie = this._web.Cookie;

    Parallel.For(0, pages, i =>
    {
        // pass in the auth'ed cookie
        var web = new CookieAwareWebClient(cookie);
        html = web.DownloadString("http://example.com/");

        someInformation += this.GetSomeInformation(html)
    });

    return someInformation;
}