您的位置:首页 > 其它

webbrowser获取跨域的sessionStorage的值和cookie的值

2014-06-15 10:04 302 查看
这是个很麻烦的问题。

我需要用webbrowser获取一个iframe中的sessionStorage值,而这个iframe是跟原页面存在跨域问题的。

最初我打算使用HtmlDocument的InvokeScript,究其原因是execScript不支持返回值。既然需要调用脚本,则我首先得要注入这段脚本。

HtmlDocument doc =
this.webbrowser.Document.Window.Frames["frame1"].Frames["frame2"].Document;
HtmlElement ele = doc.CreateElement("script");
ele.SetAttribute("type", "text/javascript");
ele.SetAttribute("text", "function test(){return window.sessionStorage[sensitiveData];}");
this.webbrowser.Document.Body.AppendChild(ele);


然后再调用invokeScript拿到脚本

this.webbrowser.Document.InvokeScript("test");
对付无跨域的问题,以上的代码已经可以完成任务了,但偏偏我遇到的就是有跨域的问题,上面代码中frame1和frame2就分别在http和https下。我尝试着在chrome和ie中执行js脚本试图拿到frame2的sessionStorage,但是失败了,每次都会报安全异常。

既然如此,能否在调用webbrowser的代码中解决这个问题呢?早有人想到并解决了,跟COM交互并解决这个跨域问题

public class CrossFrameIE
{
// Returns null in case of failure.
public static IHTMLDocument2 GetDocumentFromWindow(IHTMLWindow2 htmlWindow)
{
if (htmlWindow == null)
{
return null;
}

// First try the usual way to get the document.
try
{
IHTMLDocument2 doc = htmlWindow.document;
return doc;
}
catch (COMException comEx)
{
// I think COMException won't be ever fired but just to be sure ...
if (comEx.ErrorCode != E_ACCESSDENIED)
{
return null;
}
}
catch (System.UnauthorizedAccessException)
{
}
catch
{
// Any other error.
return null;
}

// At this point the error was E_ACCESSDENIED because the frame contains a document from another domain.
// IE tries to prevent a cross frame scripting security issue.
try
{
// Convert IHTMLWindow2 to IWebBrowser2 using IServiceProvider.
IServiceProvider sp = (IServiceProvider)htmlWindow;

// Use IServiceProvider.QueryService to get IWebBrowser2 object.
Object brws = null;
sp.QueryService(ref IID_IWebBrowserApp, ref IID_IWebBrowser2, out brws);

// Get the document from IWebBrowser2.
SHDocVw.IWebBrowser2 browser = (SHDocVw.IWebBrowser2)(brws);

return (IHTMLDocument2)browser.Document;
}
catch
{
}

return null;
}

private const int E_ACCESSDENIED = unchecked((int)0x80070005L);
private static Guid IID_IWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");
private static Guid IID_IWebBrowser2 = new Guid("D30C1661-CDAF-11D0-8A3E-00C04FC9E26E");
}

// This is the COM IServiceProvider interface, not System.IServiceProvider .Net interface!
[ComImport(), ComVisible(true), Guid("6D5140C1-7436-11CE-8034-00AA006009FA"),
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IServiceProvider
{
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int QueryService(ref Guid guidService, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppvObject);
}
到这里,问题基本有解了,但是如果继续使用invokeScript的方式,则在注入脚本的时候存在接口不匹配问题。CrossFrameIE拿到的接口是IHTMLDocument2,但是CreateElement需要的是HtmlDocument,这个差别最终导致没法建出需要的脚本,所以要想办法用另一个执行脚本的方法execScript并得到返回值,具体做法直接上代码

IHTMLWindow2 win = (IHTMLWindow2)this.webbrowser.Document.Window.Frames["frame1"].Frames["frame2"].DomWindow;
CrossFrameIE.GetDocumentFromWindow(win).parentWindow.execScript("var returnValue; function test(){alert(window.sessionStorage['sensitiveData']);} test()", "javascript");
object obj = CrossFrameIE.GetDocumentFromWindow(win).Script.returnValue;

代码可以自行修正,但是最终obj就是我们想要的值

另一个问题是如何获取cookie,一般cookie获取其实比较容易

this.webbrowser.Document.Cookie
但是经常需要获取带http_only的重要session,于是就比较复杂了,主要是调wininet.dll,据说最终是通过读取cookie文件来获取该cookie的,未考证过

private const int INTERNET_COOKIE_THIRD_PARTY = 0x00002000; //0x00002000

[DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool InternetGetCookieEx(string pchURL, string pchCookieName, StringBuilder pchCookieData, ref System.UInt32 pcchCookieData, int dwFlags, IntPtr lpReserved);

//使用下面代码片段,即可获得http_only cookie
uint datasize = 2048;
StringBuilder cookieData = new StringBuilder((int)datasize);
if (InternetGetCookieEx((string) dict["url"], null, cookieData, ref datasize, INTERNET_COOKIE_THIRD_PARTY,
IntPtr.Zero))
{
session.updateCookie(cookieData.ToString());
}


webbrowser的几个帖子
http://www.cnblogs.com/txw1958/archive/2012/09/24/CSharp-WebBrowser.html http://blog.csdn.net/jintougao/article/details/12948633 http://www.cnblogs.com/peterzb/archive/2009/07/12/1521787.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: