【急!!!】内嵌的iframe的ihtmldocument2获取到后访问数据出错

时间:2022-11-20 22:30:02
这个帖子已经解决了
【急】怎样根据iframe的name获取内嵌的iframe的ihtmldocument2?
http://topic.csdn.net/u/20110130/12/d00276b7-058f-4acc-a860-94df73f587cf.html

但是获取到的ihtmldocument2接口再获取ihtmlelement出错~ E_ACCESS_DENIED

3 个解决方案

#1


一般来说是因为IE的安全限制引起的,有两种可能:

1) 你是不是跨线程使用的IHTMLDocument2
    如果是这样,最简单的方法是你在线程中再去获取IHTMLDocument2,不要先获取了传到线程中用...
    否则就需要列集COM对象
     CoMarshalInterThreadInterfaceInStream()/CoGetInterfaceAndReleaseStream()
 
2) 你的iframe跨域了,为了避免这种情况下的XSS攻击,IE安全限制不允许你跨域操作。
不过跨域的时候在拿IHTMLDocument2应该就会出错。
这个页面上有跨域获取IHTMLDocument2的解决办法:
http://codecentrix.blogspot.com/2007/10/when-ihtmlwindow2getdocument-returns.html 

When IHTMLWindow2::get_document returns E_ACCESSDENIED
Internet Explorer extensions usually needs to access HTML elements. When extensions are initialized they get a IWebBrowser2 pointer representing the browser. Starting with this pointer one can get any HTML element in the web page but to do that we need to browse a hierarchy of frames first. The simplest web pages only have one frame and one document. Web pages containing <frame> or <iframe> have a hierarchy of frames, each frame having its own document.

Here are the objects involved and the corresponding interfaces:

browser      - IWebBrowser2
frame/iframe - IHTMLWindow2
document     - IHTMLDocument2
element      - IHTMLElement



The list bellow shows what method to call to get one object from another:

browser      -> document        IWebBrowser2::get_Document
document     -> frame           IHTMLDocument2::get_parentWindow
frame        -> document        IHTMLWindow2::get_document
frame        -> parent frame    IHTMLWindow2::get_parent
frame        -> children frames IHTMLWindow2::get_frames



A normal call chain to get a HTML element is:

browser -> document -> frame -> child frame -> ... -> child frame -> document -> element


This will work almost all the time. The problems arise when different frames contain documents loaded from different internet domains. In this case IHTMLWindow2::get_document returns E_ACCESSDENIED when trying to get the document from the frame object. I think this happens to prevent cross frame scripting atacks.

Here is HtmlWindowToHtmlDocument function I wrote to be used instead IHTMLWindow2::get_document to bypass the restriction:



// Converts a IHTMLWindow2 object to a IHTMLDocument2. Returns NULL in case of failure.
// It takes into account accessing the DOM across frames loaded from different domains.
CComQIPtr<IHTMLDocument2> HtmlWindowToHtmlDocument(CComQIPtr<IHTMLWindow2> spWindow)
{
     ATLASSERT(spWindow != NULL);

     CComQIPtr<IHTMLDocument2> spDocument;
     HRESULT hRes = spWindow->get_document(&spDocument);
    
     if ((S_OK == hRes) && (spDocument != NULL))
     {
          // The html document was properly retrieved.
          return spDocument;
     }

     // hRes could be E_ACCESSDENIED that means a security restriction that
     // prevents scripting across frames that loads documents from different internet domains.
     CComQIPtr<IWebBrowser2>  spBrws = HtmlWindowToHtmlWebBrowser(spWindow);
     if (spBrws == NULL)
     {
          return CComQIPtr<IHTMLDocument2>();
     }

     // Get the document object from the IWebBrowser2 object.
     CComQIPtr<IDispatch> spDisp;
     hRes = spBrws->get_Document(&spDisp);
     spDocument = spDisp;

     return spDocument;
}


// Converts a IHTMLWindow2 object to a IWebBrowser2. Returns NULL in case of failure.
CComQIPtr<IWebBrowser2> HtmlWindowToHtmlWebBrowser(CComQIPtr<IHTMLWindow2> spWindow)
{
     ATLASSERT(spWindow != NULL);

     CComQIPtr<IServiceProvider>  spServiceProvider = spWindow;
     if (spServiceProvider == NULL)
     {
          return CComQIPtr<IWebBrowser2>();
     }

     CComQIPtr<IWebBrowser2> spWebBrws;
     HRESULT hRes = spServiceProvider->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void**)&spWebBrws);
     if (hRes != S_OK)
     {
          return CComQIPtr<IWebBrowser2>();
     }

     return spWebBrws;
}



#2


简单说,跨域要使用IServiceProvider接口!黑白精灵的例子很好

#3


搞定了,谢谢两位!!
祝大家新年快乐
【急!!!】内嵌的iframe的ihtmldocument2获取到后访问数据出错

#1


一般来说是因为IE的安全限制引起的,有两种可能:

1) 你是不是跨线程使用的IHTMLDocument2
    如果是这样,最简单的方法是你在线程中再去获取IHTMLDocument2,不要先获取了传到线程中用...
    否则就需要列集COM对象
     CoMarshalInterThreadInterfaceInStream()/CoGetInterfaceAndReleaseStream()
 
2) 你的iframe跨域了,为了避免这种情况下的XSS攻击,IE安全限制不允许你跨域操作。
不过跨域的时候在拿IHTMLDocument2应该就会出错。
这个页面上有跨域获取IHTMLDocument2的解决办法:
http://codecentrix.blogspot.com/2007/10/when-ihtmlwindow2getdocument-returns.html 

When IHTMLWindow2::get_document returns E_ACCESSDENIED
Internet Explorer extensions usually needs to access HTML elements. When extensions are initialized they get a IWebBrowser2 pointer representing the browser. Starting with this pointer one can get any HTML element in the web page but to do that we need to browse a hierarchy of frames first. The simplest web pages only have one frame and one document. Web pages containing <frame> or <iframe> have a hierarchy of frames, each frame having its own document.

Here are the objects involved and the corresponding interfaces:

browser      - IWebBrowser2
frame/iframe - IHTMLWindow2
document     - IHTMLDocument2
element      - IHTMLElement



The list bellow shows what method to call to get one object from another:

browser      -> document        IWebBrowser2::get_Document
document     -> frame           IHTMLDocument2::get_parentWindow
frame        -> document        IHTMLWindow2::get_document
frame        -> parent frame    IHTMLWindow2::get_parent
frame        -> children frames IHTMLWindow2::get_frames



A normal call chain to get a HTML element is:

browser -> document -> frame -> child frame -> ... -> child frame -> document -> element


This will work almost all the time. The problems arise when different frames contain documents loaded from different internet domains. In this case IHTMLWindow2::get_document returns E_ACCESSDENIED when trying to get the document from the frame object. I think this happens to prevent cross frame scripting atacks.

Here is HtmlWindowToHtmlDocument function I wrote to be used instead IHTMLWindow2::get_document to bypass the restriction:



// Converts a IHTMLWindow2 object to a IHTMLDocument2. Returns NULL in case of failure.
// It takes into account accessing the DOM across frames loaded from different domains.
CComQIPtr<IHTMLDocument2> HtmlWindowToHtmlDocument(CComQIPtr<IHTMLWindow2> spWindow)
{
     ATLASSERT(spWindow != NULL);

     CComQIPtr<IHTMLDocument2> spDocument;
     HRESULT hRes = spWindow->get_document(&spDocument);
    
     if ((S_OK == hRes) && (spDocument != NULL))
     {
          // The html document was properly retrieved.
          return spDocument;
     }

     // hRes could be E_ACCESSDENIED that means a security restriction that
     // prevents scripting across frames that loads documents from different internet domains.
     CComQIPtr<IWebBrowser2>  spBrws = HtmlWindowToHtmlWebBrowser(spWindow);
     if (spBrws == NULL)
     {
          return CComQIPtr<IHTMLDocument2>();
     }

     // Get the document object from the IWebBrowser2 object.
     CComQIPtr<IDispatch> spDisp;
     hRes = spBrws->get_Document(&spDisp);
     spDocument = spDisp;

     return spDocument;
}


// Converts a IHTMLWindow2 object to a IWebBrowser2. Returns NULL in case of failure.
CComQIPtr<IWebBrowser2> HtmlWindowToHtmlWebBrowser(CComQIPtr<IHTMLWindow2> spWindow)
{
     ATLASSERT(spWindow != NULL);

     CComQIPtr<IServiceProvider>  spServiceProvider = spWindow;
     if (spServiceProvider == NULL)
     {
          return CComQIPtr<IWebBrowser2>();
     }

     CComQIPtr<IWebBrowser2> spWebBrws;
     HRESULT hRes = spServiceProvider->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void**)&spWebBrws);
     if (hRes != S_OK)
     {
          return CComQIPtr<IWebBrowser2>();
     }

     return spWebBrws;
}



#2


简单说,跨域要使用IServiceProvider接口!黑白精灵的例子很好

#3


搞定了,谢谢两位!!
祝大家新年快乐
【急!!!】内嵌的iframe的ihtmldocument2获取到后访问数据出错