为了登录到网站的某个部分,我的应用程序用户需要他们的Cookie。为此,我需要获取并将其传递到URL。
有人知道如何从浏览器控件中获取特定网站的Cookie吗?
我看到这种方法,但不是很清楚。
谢谢,TP。
有人知道如何从浏览器控件中获取特定网站的Cookie吗?
我看到这种方法,但不是很清楚。
谢谢,TP。
PropertyInfo brwhttp = typeof(System.Net.Browser.WebRequestCreator)
.GetProperty("BrowserHttp")
..不要问我是如何发现它的,或者花了多少时间:P 玩得开心
//编辑:我刚刚发现,BrowserHttp属性是访问浏览器连接工厂的正常Silverlight方式,请参见BrowserHttp。看起来它只是在为WP7平台编写的'miniSilverlight'中被隐藏了!
// 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。然后,您可以解析该字符串。
正如@quetzalcoatl已经建议的那样,您可以使用WebRequestCreator的内部实例来在浏览器实例和WebRequest实例之间共享cookie。但是,您无法直接访问cookie,我认为这只是Microsoft的安全措施。
下面的代码创建一个连接到WebBrowser实例的CookieContainer的WebReqeust对象。然后,它会发布到一个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错误。
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");
有一个专门为此开发的WebBrowser扩展类:
CookieCollection tempCookies = Microsoft.Phone.Controls.WebBrowserExtensions.GetCookies(this.BrowserControl);