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

来源:互联网 发布:动态桌面软件哪个好 编辑:程序博客网 时间:2024/06/05 08:02

  这是个很麻烦的问题。

  我需要用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

0 0
原创粉丝点击