ActiveX控件localhost可以调用,内外网IP不可以的解决办法

2 篇文章 0 订阅

开发ActiveX控件过程中遇到这样的问题:

本机上开发完成后,用TstCon测试接口没问题。js写静态页面测试调用没问题。但是给到web端开发,他们使用内网IP或者外网地址时,会报错。如图:

开始以为是IE本地设置的问题,把对ActiveX限制的都改为允许,但是试了之后还是不行。后来联想到是否是因为本地调试IE用的Intranet策略,而以IP方式访问IE采用的是Internet策略。所以果断去设置Internet选项,如图,。

点开自定义级别,

把上图中『对未标记为可安全执行脚本的ActiveX控件初始化并执行脚本』改为启用后,发现有的机器可以,有的不成,而且设置后IE会提示不安全之类的。看起来很不优雅。果断放弃修改IE设置。

仔细想想,自己写的跟官方提供的一些控件理论上除了没有数字签名外,应该没别的不同,于是尝试增加数字签名,当然这个是没有认证的。尝试后这个方案也失败了。

找资料看到这样一篇文章:http://www.xuebuyuan.com/758961.html

里面讲到,在IE的中级安全设置上,是允许脚本安全的ActiveX创建并且不予警告的。那么IE怎么知道一个插件式脚本安全的呢?

①通过查询ActiveX是否实现了IObjectSafety接口,并且返回脚本安全;

②查询ActiveX是否在注册表Component Category Manager里表明自己实现了 CATID_SafeForInitializing 和 CATID_SafeForScripting。此方法修改DllRegisterServer函数


所以,问题的关键是我们自己的ActiveX控件 实现CATID_SafeForInitializing 和 CATID_SafeForScripting,以及IObjectSafety接口。

那就来吧。

①实现CATID_SafeForInitializing  和 CATID_Safeforscripting

XXX.h中声明(以下XXX代表你的工程名,比如MyActiveX,则XXX.h表示MyActiveX.h)

包含头文件文件  #include "comcat.h"

HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription);
HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid);


①xxxCtrl.h中声明:

//ObjSafe
	DECLARE_INTERFACE_MAP()

	BEGIN_INTERFACE_PART(ObjSafe, IObjectSafety)
	STDMETHOD_(HRESULT, GetInterfaceSafetyOptions)   (
		/*   [in]   */   REFIID   riid,
		/*   [out]   */   DWORD   __RPC_FAR   *pdwSupportedOptions,
		/*   [out]   */   DWORD   __RPC_FAR   *pdwEnabledOptions
	);

	STDMETHOD_(HRESULT, SetInterfaceSafetyOptions)   (
		/*   [in]   */   REFIID   riid,
		/*   [in]   */   DWORD   dwOptionSetMask,
		/*   [in]   */   DWORD   dwEnabledOptions
	);
	END_INTERFACE_PART(ObjSafe);
②xxxCtrl.cpp中实现:

const CATID CATID_SafeForScripting =
{ 0x7dd95801, 0x9882, 0x11cf, { 0x9f, 0xa9, 0x00, 0xaa, 0x00, 0x6c, 0x42, 0xc4 } };
const CATID CATID_SafeForInitializing =
{ 0x7dd95802, 0x9882, 0x11cf, { 0x9f, 0xa9, 0x00, 0xaa, 0x00, 0x6c, 0x42, 0xc4 } };

// 创建组件种类     
HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription)
{
	ICatRegister* pcr = NULL;
	HRESULT hr = S_OK;
	hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
	if (FAILED(hr)) return hr;
	// Make sure the HKCR\Component Categories\{..catid...}      
	// key is registered.      
	CATEGORYINFO catinfo;
	catinfo.catid = catid;
	catinfo.lcid = 0x0409; // english      
	// Make sure the provided description is not too long.      
	// Only copy the first 127 characters if it is.      
	int len = wcslen(catDescription);
	if (len>127) len = 127;
	wcsncpy(catinfo.szDescription, catDescription, len);
	// Make sure the description is null terminated.      
	catinfo.szDescription[len] = '\0';
	hr = pcr->RegisterCategories(1, &catinfo);
	pcr->Release();
	return hr;
}

// 注册组件种类     
HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
{
	// Register your component categories information.      
	ICatRegister* pcr = NULL;
	HRESULT hr = S_OK;
	hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
	if (SUCCEEDED(hr)) {
		// Register this category as being "implemented" by the class.      
		CATID rgcatid[1];
		rgcatid[0] = catid;
		hr = pcr->RegisterClassImplCategories(clsid, 1, rgcatid);
	}
	if (pcr != NULL) pcr->Release();
	return hr;
}
STDAPI DllRegisterServer(void) 函数中,添加:

// 标记控件初始化安全.      
	// 创建初始化安全组件种类     
	HRESULT hr = CreateComponentCategory(CATID_SafeForInitializing, L"Controls safely initializable from persistent data!");
	if (FAILED(hr)) return hr;
	// 注册初始化安全     
	hr = RegisterCLSIDInCategory(BASED_CODE _tlid, CATID_SafeForInitializing);
	if (FAILED(hr)) return hr;
	// 标记控件脚本安全     
	// 创建脚本安全组件种类     
	hr = CreateComponentCategory(CATID_SafeForScripting, L"Controls safely scriptable!");
	if (FAILED(hr)) return hr;
	// 注册脚本安全组件种类     
	hr = RegisterCLSIDInCategory(BASED_CODE _tlid, CATID_SafeForScripting);
	if (FAILED(hr)) return hr;


STDAPI DllUnregisterServer(void) 中添加:

// 删除控件初始化安全入口. 
HRESULT hr = UnRegisterCLSIDInCategory(BASED_CODE _tlid, CATID_SafeForInitializing);
	if (FAILED(hr)) return hr;
	// 删除控件脚本安全入口     
	hr = UnRegisterCLSIDInCategory(BASED_CODE _tlid, CATID_SafeForScripting);
	if (FAILED(hr)) return hr;


xxxCtrl.h中添加:

//ObjSafe
	DECLARE_INTERFACE_MAP()

	BEGIN_INTERFACE_PART(ObjSafe, IObjectSafety)
	STDMETHOD_(HRESULT, GetInterfaceSafetyOptions)   (
		/*   [in]   */   REFIID   riid,
		/*   [out]   */   DWORD   __RPC_FAR   *pdwSupportedOptions,
		/*   [out]   */   DWORD   __RPC_FAR   *pdwEnabledOptions
	);

	STDMETHOD_(HRESULT, SetInterfaceSafetyOptions)   (
		/*   [in]   */   REFIID   riid,
		/*   [in]   */   DWORD   dwOptionSetMask,
		/*   [in]   */   DWORD   dwEnabledOptions
	);
	END_INTERFACE_PART(ObjSafe);


xxxCtrl.cpp中添加:

//接口映射
BEGIN_INTERFACE_MAP(CRtmpDumpCtrlCtrl, COleControl)
	INTERFACE_PART(CRtmpDumpCtrlCtrl, IID_IObjectSafety, ObjSafe)
END_INTERFACE_MAP()

ULONG FAR EXPORT CRtmpDumpCtrlCtrl::XObjSafe::AddRef()
{
	METHOD_PROLOGUE(CRtmpDumpCtrlCtrl, ObjSafe)
	return pThis->ExternalAddRef();
}

ULONG FAR EXPORT CRtmpDumpCtrlCtrl::XObjSafe::Release()
{
	METHOD_PROLOGUE(CRtmpDumpCtrlCtrl, ObjSafe)
		return pThis->ExternalRelease();
}

HRESULT FAR EXPORT CRtmpDumpCtrlCtrl::XObjSafe::QueryInterface(REFIID iid, void FAR* FAR* ppvObj)
{
	METHOD_PROLOGUE(CRtmpDumpCtrlCtrl, ObjSafe)
	return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
}

const DWORD dwSupportedBits = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
const DWORD dwNotSupportedBits = ~dwSupportedBits;

HRESULT   STDMETHODCALLTYPE
CRtmpDumpCtrlCtrl::XObjSafe::GetInterfaceSafetyOptions(
/* [in] */ REFIID riid,
/* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,
/* [out] */ DWORD __RPC_FAR *pdwEnabledOptions)
{
	METHOD_PROLOGUE(CRtmpDumpCtrlCtrl, ObjSafe)
	HRESULT retval = ResultFromScode(S_OK);
	// does interface exist?   
	IUnknown FAR* punkInterface;
	retval = pThis->ExternalQueryInterface(&riid, (void **)&punkInterface);
	if (retval != E_NOINTERFACE)
	{ // interface exists   
		punkInterface->Release(); // release it--just checking!   
	}
	// we support both kinds of safety and have always both set, regardless of interface   
	*pdwSupportedOptions = *pdwEnabledOptions = dwSupportedBits;
	return retval; // E_NOINTERFACE if QI failed   
}

HRESULT STDMETHODCALLTYPE
CRtmpDumpCtrlCtrl::XObjSafe::SetInterfaceSafetyOptions(
/* [in] */ REFIID riid,
/* [in] */ DWORD dwOptionSetMask,
/* [in] */ DWORD dwEnabledOptions)
{
	METHOD_PROLOGUE(CRtmpDumpCtrlCtrl, ObjSafe)
		// does interface exist? 
	IUnknown FAR* punkInterface;
	pThis->ExternalQueryInterface(&riid, (void**)&punkInterface);
	if (punkInterface)
	{ // interface exists 
		punkInterface->Release(); // release it--just checking! 
	}
	else
	{ // interface doesn't exist 
		return ResultFromScode(E_NOINTERFACE);
	}

	// can't set bits we don't support 
	if (dwOptionSetMask & dwNotSupportedBits)
	{
		return ResultFromScode(E_FAIL);
	}

	// can't set bits we do support to zero 
	dwEnabledOptions &= dwSupportedBits;
	// (we already know there are no extra bits   in   mask   )   
	if ((dwOptionSetMask&dwEnabledOptions) != dwOptionSetMask)
	{
		return ResultFromScode(E_FAIL);
	}
	//don't need to change anything since we're always safe 
	return ResultFromScode(S_OK);
}

参考文章:

https://support.microsoft.com/zh-cn/kb/161873

https://msdn.microsoft.com/zh-cn/library/aa751977(v=vs.85).aspx

http://blog.sina.com.cn/s/blog_4f9fc08e01014ipt.html

http://www.xuebuyuan.com/758961.html

http://blog.csdn.net/aasmfox/article/details/38616997

乌云的两篇好文:

http://drops.wooyun.org/papers/5673

http://drops.wooyun.org/papers/7521





  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值