分享

C#中webBrowser加载页面中访问不同域的iFrame引发System.UnauthorizedAccessException异常的解决办法

 franklinfj 2013-11-23

C#中webBrowser加载页面中访问不同域的iFrame引发System.UnauthorizedAccessException异常的解决办法

分类: 01_C#.NET1585人阅读评论(1)收藏举报

使用WebBrowser打开一个页面,在该页面中有一个iFrame,在WebBrowser完全打开页面后,获取该iFrame的时候总是引发System.UnauthorizedAccessException异常。

  1. Console.WriteLine(this.webMain.Document.Window.Frames[0].Url);

“this.webMain.Document.Window.Frames[0].Url”引发了“System.UnauthorizedAccessException”类型的异常
base {System.SystemException}: {"拒绝访问。 (异常来自 HRESULT:0x80070005 (E_ACCESSDENIED))"}

最近这个跨域的安全问题很困扰,搞了好久,终于在朋友的帮助下找到了一个C++的方法HtmlWindowToHtmlWebBrowser

  1. CComPtr<IWebBrowser2> CTimerSerachDlg::HtmlWindowToHtmlWebBrowser(CComPtr<IHTMLWindow2> spWindow)
  2. {
  3. ATLASSERT(spWindow != NULL);
  4. CComQIPtr<IServiceProvider> spServiceProvider = spWindow;
  5. if (spServiceProvider == NULL)
  6. {
  7. return CComPtr<IWebBrowser2>();
  8. }
  9. CComPtr<IWebBrowser2> spWebBrws;
  10. HRESULT hRes = spServiceProvider->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void**)&spWebBrws);
  11. if (hRes != S_OK)
  12. {
  13. return CComPtr<IWebBrowser2>();
  14. }
  15. return spWebBrws;
  16. }
  17. // Converts a IHTMLWindow2 object to a IHTMLDocument2. Returns NULL in case of failure.
  18. // It takes into account accessing the DOM across frames loaded from different domains.
  19. CComPtr<IHTMLDocument2> CTimerSerachDlg::HtmlWindowToHtmlDocument(CComPtr<IHTMLWindow2> spWindow)
  20. {
  21. ATLASSERT(spWindow != NULL);
  22. CComPtr<IHTMLDocument2> spDocument;
  23. HRESULT hRes = spWindow->get_document(&spDocument);
  24. if ((S_OK == hRes) && (spDocument != NULL))
  25. {
  26. // The html document was properly retrieved.
  27. return spDocument;
  28. }
  29. // hRes could be E_ACCESSDENIED that means a security restriction that
  30. // prevents scripting across frames that loads documents from different internet domains.
  31. CComPtr<IWebBrowser2> spBrws = HtmlWindowToHtmlWebBrowser(spWindow);
  32. if (spBrws == NULL)
  33. {
  34. return CComPtr<IHTMLDocument2>();
  35. }
  36. // Get the document object from the IWebBrowser2 object.
  37. CComPtr<IDispatch> spDisp; hRes = spBrws->get_Document(&spDisp);
  38. spDocument = spDisp;
  39. return spDocument;
  40. }

在后来找到了作者的Blog,但是国内屏蔽了blogspot,直接不能够访问。

然后发现了作者的另外一篇文章:http://codecentrix./2008/02/when-ihtmlwindow2document-throws.html

C# 跨域访问iframe的办法:http://www./blog/wnd2doc_csharp/GetDocumentFromWindowCsharp.zip

  1. mshtml.HTMLDocumentClass htmlDoc = this.webMain.Document.DomDocument as mshtml.HTMLDocumentClass;
  2. object index = 0;
  3. mshtml.IHTMLWindow2 frameWindow = htmlDoc.frames.item(ref index) as mshtml.IHTMLWindow2;
  4. Console.WriteLine( CodecentrixSample.CrossFrameIE.GetDocumentFromWindow(frameWindow).activeElement.innerHTML);

接口转换的代码:

  1. using System;
  2. using System.Runtime.InteropServices;
  3. using mshtml;
  4. namespace CodecentrixSample
  5. {
  6. public class CrossFrameIE
  7. {
  8. // Returns null in case of failure.
  9. public static IHTMLDocument2 GetDocumentFromWindow(IHTMLWindow2 htmlWindow)
  10. {
  11. if (htmlWindow == null)
  12. {
  13. return null;
  14. }
  15. // First try the usual way to get the document.
  16. try
  17. {
  18. IHTMLDocument2 doc = htmlWindow.document;
  19. return doc;
  20. }
  21. catch (COMException comEx)
  22. {
  23. // I think COMException won't be ever fired but just to be sure ...
  24. if (comEx.ErrorCode != E_ACCESSDENIED)
  25. {
  26. return null;
  27. }
  28. }
  29. catch (System.UnauthorizedAccessException)
  30. {
  31. }
  32. catch
  33. {
  34. // Any other error.
  35. return null;
  36. }
  37. // At this point the error was E_ACCESSDENIED because the frame contains a document from another domain.
  38. // IE tries to prevent a cross frame scripting security issue.
  39. try
  40. {
  41. // Convert IHTMLWindow2 to IWebBrowser2 using IServiceProvider.
  42. IServiceProvider sp = (IServiceProvider)htmlWindow;
  43. // Use IServiceProvider.QueryService to get IWebBrowser2 object.
  44. Object brws = null;
  45. sp.QueryService(ref IID_IWebBrowserApp, ref IID_IWebBrowser2, out brws);
  46. // Get the document from IWebBrowser2.
  47. SHDocVw.IWebBrowser2 browser = (SHDocVw.IWebBrowser2)(brws);
  48. return (IHTMLDocument2)browser.Document;
  49. }
  50. catch
  51. {
  52. }
  53. return null;
  54. }
  55. private const int E_ACCESSDENIED = unchecked((int)0x80070005L);
  56. private static Guid IID_IWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");
  57. private static Guid IID_IWebBrowser2 = new Guid("D30C1661-CDAF-11D0-8A3E-00C04FC9E26E");
  58. }
  59. // This is the COM IServiceProvider interface, not System.IServiceProvider .Net interface!
  60. [ComImport(), ComVisible(true), Guid("6D5140C1-7436-11CE-8034-00AA006009FA"),
  61. InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
  62. public interface IServiceProvider
  63. {
  64. [return: MarshalAs(UnmanagedType.I4)][PreserveSig]
  65. int QueryService(ref Guid guidService, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppvObject);
  66. }
  67. }

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多