.NET WebBrowser 粘贴安全限制
.NET WebBrowser Paste Security Restriction
我在 C# WPF 应用程序中使用 WebBrowser 控件。我需要以编程方式执行粘贴命令,我使用以下语句执行此操作:
WebBrowser.Document.ExecCommand("paste", false, null);
这在我的本地机器上完美运行;但是,它在我们的生产环境中不起作用。该命令什么都不做。幸运的是,基于 this post.
,我确定此问题的原因是 IE 安全限制
修复方法是将 IE 中的安全级别修改为中等(工具 > Internet 选项 > 安全 > Internet > 中等级别)。
按照 post 的回答,问题可以解决。但是在我们的生产环境中,IE的安全设置是高的,因为安全策略的原因是不能修改的。因此无法使用此修复程序。
我看到另一个 post 关于添加自定义安全管理器,这听起来像是解决这个问题的可能方法。
但是,我无法准确确定我需要实施哪些 IInternetSecurityManager 方法或如何实施它们。我已经定义了接口并获得了要调用的方法,但我目前只是为所有这些方法返回 INET_E_DEFAULT_ACTION。
public class MyWebBrowser : WebBrowser
{
protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
{
return new ExtendedWebBrowserSite(this);
}
protected class ExtendedWebBrowserSite : WebBrowserSite, IInternetSecurityManager, IServiceProvider
{
private static readonly Guid SID_IInternetSecurityManager = new Guid("79EAC9EE-BAF9-11CE-8C82-00AA004BA90B");
WebBrowser _host;
public ExtendedWebBrowserSite(WebBrowser host) : base(host)
{
_host = host;
}
public int QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject)
{
if (guidService == SID_IInternetSecurityManager && riid == SID_IInternetSecurityManager)
{
ppvObject = Marshal.GetComInterfaceForObject(this, typeof(IInternetSecurityManager));
return HRESULTS.S_OK;
}
ppvObject = IntPtr.Zero;
return HRESULTS.E_NOINTERFACE;
}
#region IInternetSecurityManager Implementation
public int SetSecuritySite([In] IntPtr pSite)
{
return URLMonikerErrorCodes.INET_E_DEFAULT_ACTION;
}
public int GetSecuritySite([Out] IntPtr pSite)
{
return URLMonikerErrorCodes.INET_E_DEFAULT_ACTION;
}
public int MapUrlToZone([In, MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, out uint pdwZone, uint dwFlags)
{
pdwZone = 0;
return URLMonikerErrorCodes.INET_E_DEFAULT_ACTION;
}
public int GetSecurityId([MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, [MarshalAs(UnmanagedType.LPArray)] byte[] pbSecurityId, ref uint pcbSecurityId, uint dwReserved)
{
return URLMonikerErrorCodes.INET_E_DEFAULT_ACTION;
}
public int ProcessUrlAction([In, MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, uint dwAction, out byte pPolicy, uint cbPolicy, byte pContext, uint cbContext, uint dwFlags, uint dwReserved)
{
pPolicy = 0;
return URLMonikerErrorCodes.INET_E_DEFAULT_ACTION;
}
public int QueryCustomPolicy([In, MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, ref Guid guidKey, ref byte ppPolicy, ref uint pcbPolicy, ref byte pContext, uint cbContext, uint dwReserved)
{
return URLMonikerErrorCodes.INET_E_DEFAULT_ACTION;
}
public int SetZoneMapping(uint dwZone, [In, MarshalAs(UnmanagedType.LPWStr)] string lpszPattern, uint dwFlags)
{
return URLMonikerErrorCodes.INET_E_DEFAULT_ACTION;
}
public int GetZoneMappings(uint dwZone, out IEnumString ppenumString, uint dwFlags)
{
ppenumString = null;
return URLMonikerErrorCodes.INET_E_DEFAULT_ACTION;
}
#endregion IInternetSecurityManager Implementation
}
}
我应该实施哪些方法来修复粘贴功能,如何实施?
好的,我相信我已经弄明白了。我有一个解决问题的实现,虽然我还没有彻底测试它,所以它可能有也可能没有一些不需要的副作用。
如果您扩展 WebBrowser 控件(我们称它为 MyWebBrowser)然后覆盖 CreateWebBrowserSiteBase
方法,您可以提供您自己的 WebBrowserSite 派生的 class(我们称它为 ExtendedWebBrowserSite)来实现必要的 COM 接口(在本例中,IServiceProvider
和 IInternetSecurityManager
)。
然后在 ExtendedWebBrowserSite class 中,我们需要实现 IServiceProvider.QueryService
方法,这样它将 return IInternetSecurityManager 的正确实现。然后我们还需要实现 IInternetSecurityManager 的所有方法。这里重要的方法是IInternetSecurityManager.ProcessUrlAction
,需要覆盖默认逻辑。其余的 IInternetSecurityManager 方法只需要 return INET_E_DEFAULT_ACTION, to ensure that the default security manager handles those actions. The IInternetSecurityManager.ProcessUrlAction
method should check if the action is URLACTION_SCRIPT_PASTE. If it is, then we should set the pPolicy
out parameter to URLPOLICY_ALLOW and return S_OK. Otherwise, we should return INET_E_DEFAULT_ACTION. I'm pretty sure that if we return INET_E_DEFAULT_ACTION,将 pPolicy 设置为什么值并不重要,因为它会被忽略。如果我在这里错了,请纠正我。
我的网络浏览器:
class MyWebBrowser : System.Windows.Forms.WebBrowser
{
protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
{
return new ExtendedWebBrowserSite(this);
}
}
ExtendedWebBrowserSite:
class ExtendedWebBrowserSite : WebBrowserSite, IInternetSecurityManager, IServiceProvider
{
// constructor omitted
int IServiceProvider.QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject)
{
if (guidService == SID_IInternetSecurityManager && riid == SID_IInternetSecurityManager)
{
ppvObject = Marshal.GetComInterfaceForObject(this, typeof(IInternetSecurityManager));
return HRESULTS.S_OK;
}
ppvObject = IntPtr.Zero;
return HRESULTS.E_NOINTERFACE;
}
int IInternetSecurityManager.ProcessUrlAction([In, MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, uint dwAction, out byte pPolicy, uint cbPolicy, byte pContext, uint cbContext, uint dwFlags, uint dwReserved)
{
// If action is a paste, then we want to allow it, regardless of the inherited IE security policy.
if (dwAction == URLActionFlags.URLACTION_SCRIPT_PASTE)
{
pPolicy = URLPolicyFlags.URLPOLICY_ALLOW;
return HRESULTS.S_OK;
}
// I think we can set the policy to whatever arbitrary value we want here.
// Because if we return INET_E_DEFAULT_ACTION, the policy value will just be ignored.
pPolicy = URLPolicyFlags.URLPOLICY_ALLOW;
return URLMonikerErrorCodes.INET_E_DEFAULT_ACTION;
}
// Other IInternetSecurityManager methods omitted for brevity...
// Other IInternetSecurityManager methods should all return INET_E_DEFAULT_ACTION to ensure that the default security manager handles them.
}
COM 接口定义
[ComImport, Guid("6D5140C1-7436-11CE-8034-00AA006009FA")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IServiceProvider
{
[PreserveSig]
int QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject);
}
[ComImport, Guid("79EAC9EE-BAF9-11CE-8C82-00AA004BA90B")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IInternetSecurityManager
{
[PreserveSig]
int SetSecuritySite([In] IntPtr pSite);
[PreserveSig]
int GetSecuritySite([Out] IntPtr pSite);
[PreserveSig]
int MapUrlToZone([In,MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, out UInt32 pdwZone, UInt32 dwFlags);
[PreserveSig]
int GetSecurityId([MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, [MarshalAs(UnmanagedType.LPArray)] byte[] pbSecurityId, ref UInt32 pcbSecurityId, uint dwReserved);
[PreserveSig]
int ProcessUrlAction([In,MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, UInt32 dwAction, out byte pPolicy, UInt32 cbPolicy, byte pContext, UInt32 cbContext, UInt32 dwFlags, UInt32 dwReserved);
[PreserveSig]
int QueryCustomPolicy([In,MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, ref Guid guidKey, ref byte ppPolicy, ref UInt32 pcbPolicy, ref byte pContext, UInt32 cbContext, UInt32 dwReserved);
[PreserveSig]
int SetZoneMapping(UInt32 dwZone, [In,MarshalAs(UnmanagedType.LPWStr)] string lpszPattern, UInt32 dwFlags);
[PreserveSig]
int GetZoneMappings(UInt32 dwZone, out IEnumString ppenumString, UInt32 dwFlags);
}
我在 C# WPF 应用程序中使用 WebBrowser 控件。我需要以编程方式执行粘贴命令,我使用以下语句执行此操作:
WebBrowser.Document.ExecCommand("paste", false, null);
这在我的本地机器上完美运行;但是,它在我们的生产环境中不起作用。该命令什么都不做。幸运的是,基于 this post.
,我确定此问题的原因是 IE 安全限制修复方法是将 IE 中的安全级别修改为中等(工具 > Internet 选项 > 安全 > Internet > 中等级别)。
按照 post 的回答,问题可以解决。但是在我们的生产环境中,IE的安全设置是高的,因为安全策略的原因是不能修改的。因此无法使用此修复程序。
我看到另一个 post 关于添加自定义安全管理器,这听起来像是解决这个问题的可能方法。
但是,我无法准确确定我需要实施哪些 IInternetSecurityManager 方法或如何实施它们。我已经定义了接口并获得了要调用的方法,但我目前只是为所有这些方法返回 INET_E_DEFAULT_ACTION。
public class MyWebBrowser : WebBrowser
{
protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
{
return new ExtendedWebBrowserSite(this);
}
protected class ExtendedWebBrowserSite : WebBrowserSite, IInternetSecurityManager, IServiceProvider
{
private static readonly Guid SID_IInternetSecurityManager = new Guid("79EAC9EE-BAF9-11CE-8C82-00AA004BA90B");
WebBrowser _host;
public ExtendedWebBrowserSite(WebBrowser host) : base(host)
{
_host = host;
}
public int QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject)
{
if (guidService == SID_IInternetSecurityManager && riid == SID_IInternetSecurityManager)
{
ppvObject = Marshal.GetComInterfaceForObject(this, typeof(IInternetSecurityManager));
return HRESULTS.S_OK;
}
ppvObject = IntPtr.Zero;
return HRESULTS.E_NOINTERFACE;
}
#region IInternetSecurityManager Implementation
public int SetSecuritySite([In] IntPtr pSite)
{
return URLMonikerErrorCodes.INET_E_DEFAULT_ACTION;
}
public int GetSecuritySite([Out] IntPtr pSite)
{
return URLMonikerErrorCodes.INET_E_DEFAULT_ACTION;
}
public int MapUrlToZone([In, MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, out uint pdwZone, uint dwFlags)
{
pdwZone = 0;
return URLMonikerErrorCodes.INET_E_DEFAULT_ACTION;
}
public int GetSecurityId([MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, [MarshalAs(UnmanagedType.LPArray)] byte[] pbSecurityId, ref uint pcbSecurityId, uint dwReserved)
{
return URLMonikerErrorCodes.INET_E_DEFAULT_ACTION;
}
public int ProcessUrlAction([In, MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, uint dwAction, out byte pPolicy, uint cbPolicy, byte pContext, uint cbContext, uint dwFlags, uint dwReserved)
{
pPolicy = 0;
return URLMonikerErrorCodes.INET_E_DEFAULT_ACTION;
}
public int QueryCustomPolicy([In, MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, ref Guid guidKey, ref byte ppPolicy, ref uint pcbPolicy, ref byte pContext, uint cbContext, uint dwReserved)
{
return URLMonikerErrorCodes.INET_E_DEFAULT_ACTION;
}
public int SetZoneMapping(uint dwZone, [In, MarshalAs(UnmanagedType.LPWStr)] string lpszPattern, uint dwFlags)
{
return URLMonikerErrorCodes.INET_E_DEFAULT_ACTION;
}
public int GetZoneMappings(uint dwZone, out IEnumString ppenumString, uint dwFlags)
{
ppenumString = null;
return URLMonikerErrorCodes.INET_E_DEFAULT_ACTION;
}
#endregion IInternetSecurityManager Implementation
}
}
我应该实施哪些方法来修复粘贴功能,如何实施?
好的,我相信我已经弄明白了。我有一个解决问题的实现,虽然我还没有彻底测试它,所以它可能有也可能没有一些不需要的副作用。
如果您扩展 WebBrowser 控件(我们称它为 MyWebBrowser)然后覆盖 CreateWebBrowserSiteBase
方法,您可以提供您自己的 WebBrowserSite 派生的 class(我们称它为 ExtendedWebBrowserSite)来实现必要的 COM 接口(在本例中,IServiceProvider
和 IInternetSecurityManager
)。
然后在 ExtendedWebBrowserSite class 中,我们需要实现 IServiceProvider.QueryService
方法,这样它将 return IInternetSecurityManager 的正确实现。然后我们还需要实现 IInternetSecurityManager 的所有方法。这里重要的方法是IInternetSecurityManager.ProcessUrlAction
,需要覆盖默认逻辑。其余的 IInternetSecurityManager 方法只需要 return INET_E_DEFAULT_ACTION, to ensure that the default security manager handles those actions. The IInternetSecurityManager.ProcessUrlAction
method should check if the action is URLACTION_SCRIPT_PASTE. If it is, then we should set the pPolicy
out parameter to URLPOLICY_ALLOW and return S_OK. Otherwise, we should return INET_E_DEFAULT_ACTION. I'm pretty sure that if we return INET_E_DEFAULT_ACTION,将 pPolicy 设置为什么值并不重要,因为它会被忽略。如果我在这里错了,请纠正我。
我的网络浏览器:
class MyWebBrowser : System.Windows.Forms.WebBrowser
{
protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
{
return new ExtendedWebBrowserSite(this);
}
}
ExtendedWebBrowserSite:
class ExtendedWebBrowserSite : WebBrowserSite, IInternetSecurityManager, IServiceProvider
{
// constructor omitted
int IServiceProvider.QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject)
{
if (guidService == SID_IInternetSecurityManager && riid == SID_IInternetSecurityManager)
{
ppvObject = Marshal.GetComInterfaceForObject(this, typeof(IInternetSecurityManager));
return HRESULTS.S_OK;
}
ppvObject = IntPtr.Zero;
return HRESULTS.E_NOINTERFACE;
}
int IInternetSecurityManager.ProcessUrlAction([In, MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, uint dwAction, out byte pPolicy, uint cbPolicy, byte pContext, uint cbContext, uint dwFlags, uint dwReserved)
{
// If action is a paste, then we want to allow it, regardless of the inherited IE security policy.
if (dwAction == URLActionFlags.URLACTION_SCRIPT_PASTE)
{
pPolicy = URLPolicyFlags.URLPOLICY_ALLOW;
return HRESULTS.S_OK;
}
// I think we can set the policy to whatever arbitrary value we want here.
// Because if we return INET_E_DEFAULT_ACTION, the policy value will just be ignored.
pPolicy = URLPolicyFlags.URLPOLICY_ALLOW;
return URLMonikerErrorCodes.INET_E_DEFAULT_ACTION;
}
// Other IInternetSecurityManager methods omitted for brevity...
// Other IInternetSecurityManager methods should all return INET_E_DEFAULT_ACTION to ensure that the default security manager handles them.
}
COM 接口定义
[ComImport, Guid("6D5140C1-7436-11CE-8034-00AA006009FA")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IServiceProvider
{
[PreserveSig]
int QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject);
}
[ComImport, Guid("79EAC9EE-BAF9-11CE-8C82-00AA004BA90B")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IInternetSecurityManager
{
[PreserveSig]
int SetSecuritySite([In] IntPtr pSite);
[PreserveSig]
int GetSecuritySite([Out] IntPtr pSite);
[PreserveSig]
int MapUrlToZone([In,MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, out UInt32 pdwZone, UInt32 dwFlags);
[PreserveSig]
int GetSecurityId([MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, [MarshalAs(UnmanagedType.LPArray)] byte[] pbSecurityId, ref UInt32 pcbSecurityId, uint dwReserved);
[PreserveSig]
int ProcessUrlAction([In,MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, UInt32 dwAction, out byte pPolicy, UInt32 cbPolicy, byte pContext, UInt32 cbContext, UInt32 dwFlags, UInt32 dwReserved);
[PreserveSig]
int QueryCustomPolicy([In,MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, ref Guid guidKey, ref byte ppPolicy, ref UInt32 pcbPolicy, ref byte pContext, UInt32 cbContext, UInt32 dwReserved);
[PreserveSig]
int SetZoneMapping(UInt32 dwZone, [In,MarshalAs(UnmanagedType.LPWStr)] string lpszPattern, UInt32 dwFlags);
[PreserveSig]
int GetZoneMappings(UInt32 dwZone, out IEnumString ppenumString, UInt32 dwFlags);
}