在Web浏览器控件中抓取Cookie - WP7

时间:2010-11-18 07:58:48

标签: c# silverlight windows-phone-7 webbrowser-control

为了登录网站的某个部分,我的应用程序的用户需要他们的cookie。要做到这一点,我需要抓住它并将其传递给url。

有谁知道如何从浏览器控件中获取某个网站cookie?

我看到this method但不太清楚。

谢谢,TP。

5 个答案:

答案 0 :(得分:6)

从WP 7.1芒果“发布”开始,如果可以打电话,请参阅WebBrowser Control Overview for Windows Phone。它最近已经更新了一点,事实证明它们实际上已经从WebBrowser添加了对cookie检索的一些支持。在页面的底部,您会发现一个微小的链接GetCookies(WebBrowser)指向一个新类的描述:WebBrowserExtensions使用这个非常方便的方法。是的,这个班级只有一个成员。这是一种扩展方法,我想不需要解释。

我没有多玩过这种方法,但似乎这将允许你访问与JS技巧完全相同的东西:当前URL的cookie集。它可能不允许设置任何内容,也不允许查看其他URL的cookie。也许如果你努力玩CookieContainer,你会收到,但我怀疑。

在7.0版本中,我一直在努力为我的应用程序实现“cookie透明度”。长话短说,我的应用程序正在做一些后台HTTP请求,并且还有一个WebBrowser来显示一些在线内容 - 如果两个连接源都向服务器发出相同的cookie,那么“会很棒”。猜猜是什么,我的应用程序发出第一个请求,然后让浏览器导航。有了这样的要求,实际上几乎没有办法实现cookies的一致性 - 即使使用当前新的和光荣的GetCookie方法,我想这将是非常难的。所以,重点 - 它是可能的,但需要使用一些隐藏的API,它在电话上公开存在,但隐藏在SDK中。该API可用于(公共)类 System.Net.Browser.WebRequestCreator ,可免费使用。怪癖是:在SDK中,这个类有一个公共静态属性“IWebRequestCreate ClientHttp”,其中有一个方法“Create”,可用于“生产”你的“原始http”连接 - 如果你不想使用WebClient某些原因。在手机和模拟器上,有一个第二个公共静态属性,名为“IWebRequestCreate BrowserHttp”,很容易被Reflection返回:

PropertyInfo brwhttp = typeof(System.Net.Browser.WebRequestCreator)
    .GetProperty("BrowserHttp")

使用此属性,您将能够获得WebBrowser内部使用的IWebRequestCreate的“特殊”内部实例。通过使用此类打开您的后台HTTP请求,您将自动设置Cookie,就好像它们是由WebBrowser控件创建/发送的,但反过来 - 您将无法修改 http标头,用户提供http用户身份验证,并且都没有做一些低级别的事情 - 因为所有这些设置都将与为当前“系统用户实例”存储的WebBrowser数据同步,如果我被允许在其上调用它单用户手机设备嘿。连接和WebBrowser之间的互操作双向 - 如果您的HTTP连接(使用'hidden property'创建)接收任何设置/ cookies /等 - 那么WebBrowser会立即注意到它们和更新自己的缓存。任何一方都没有cookie /会话损失!

如果您需要在第一次WebBrowser导航后为您的后续连接被动获取Cookie,请使用GetCookie或JS方式。 但是如果你需要你的代码是第一个,然后将authz传递给WebBrowser - 你可能需要深入挖掘并使用上面的内容..它已被隐藏,所以请先采用其他方法!

..并且不要问我是如何找到它或花了多少时间:P 用它玩得很开心

//编辑:我刚刚发现,BrowserHttp属性是访问浏览器连接工厂的正常Silverlight方式,请参阅BrowserHttp。它似乎只是隐藏在为WP7平台编写的'miniSilverlight'中!

答案 1 :(得分:0)

您链接的帖子中描述的方法是使用WebBrowser控件的InvokeScript方法运行一些javascript。但是这篇文章似乎使用了一个实际上并不存在的“cookies”集合。

 string cookie = myWebBrowser.InvokeScript("document.cookie") as string;

现在,对于困难的部分,您获得的字符串包含页面的所有相关cookie名称/值对,其值仍为Url编码。您需要解析返回的字符串以获取所需的值。

请参阅document.cookie property文档。

修改

看起来很新而不是依赖帖子,InvokeScript在主机浏览器的窗口上调用命名函数。因此,WebBrowser中显示的页面本身需要包含如下函数: -

 function getCookie() { return document.cookie; }

然后InvokeScript看起来像: -

 string cookie = myWebBrowser.InvokeScript("getCookie");

答案 2 :(得分:0)

// Ensure this is set to true BEFORE navigating to the page
webBrowser1.IsScriptEnabled = true;

// Once the page has loaded, you can read the cookie string
string cookieString = webBrowser1.InvokeScript("eval", new string[] { "document.cookie;" }) as string;

cookieString变量将包含文档的完整cookie。然后,您可以解析字符串。

答案 3 :(得分:0)

正如@quetzalcoatl已经建议的那样,您可以使用WebRequestCreator的内部实例在浏览器实例和WebRequest实例之间共享cookie。你不能直接访问cookie,我认为这只是微软的一项安全措施。

下面的代码创建了一个WebReqeust对象,该对象连接到WebBrowser实例的CookieContainer。然后它发布到URL以登录用户并将cookie存储在容器中。 完成后,应用程序实例中的所有浏览器实例都将具有所需的一组cookie。

var browser = new WebBrowser();
var brwhttp = typeof (WebRequestCreator).GetProperty("BrowserHttp");
var requestFactory = brwhttp.GetValue(browser, null) as IWebRequestCreate;
var uri = new Uri("https://www.login.com/login-handler");

var req = requestFactory.Create(uri);
req.Method = "POST";

var postParams = new Dictionary<string, string> { 
    {"username", "turtlepower"}, 
    {"password": "ZoMgPaSSw0Rd1"}
};

req.BeginGetRequestStream(aReq => {

    var webRequest = (HttpWebRequest)aReq.AsyncState;
    using (var postStream = webRequest.EndGetRequestStream(aReq)) {

        // Build your POST request here
        var postDataBuilder = new StringBuilder();
        foreach (var pair in paramsDict) {
            if (postDataBuilder.Length != 0) {
                postDataBuilder.Append("&");
            }
            postDataBuilder.AppendFormat("{0}={1}", pair.Key, HttpUtility.UrlEncode(pair.Value));
        }

        var bytes = Encoding.UTF8.GetBytes(postDataBuilder.ToString());
        postStream.Write(bytes, 0, bytes.Length);
    }

    // Receive response 
    webRequest.BeginGetResponse(aResp => {

        var webRequest2 = (HttpWebRequest) aResp.AsyncState;

        webRequest = (HttpWebRequest)aResp.AsyncState;
        string resp;

        using (var response = (HttpWebResponse)webRequest2.EndGetResponse(aResp)) {
            using (var streamResponse = response.GetResponseStream()) {
                using (var streamReader = new System.IO.StreamReader(streamResponse)) {
                    resp = streamReader.ReadToEnd();
                }
            }
        }

    }, webRequest);
}, req);

我无法解决的问题之一是当服务器返回302时抛出的异常 - 它似乎抛出了“未找到”描述的WebException错误。

答案 4 :(得分:0)

有一个WebBrowser Extension类,它是为此精确开发的:

CookieCollection tempCookies = Microsoft.Phone.Controls.WebBrowserExtensions.GetCookies(this.BrowserControl);