自定義ActiveX控件幫助WEB端跳過沙箱訪問用戶系統資源

引文

        B/S模式下,由於瀏覽器的沙箱系統,瀏覽器無法直接訪問用戶本地的系統資源,那麼問題來了:

        如果要做一個超市收銀系統,怎麼使用掃碼器呢?

        如果要做個網吧管理系統,怎麼使用讀卡器呢?

        如果要做個系統要調用打印機、密碼鍵盤、高拍儀等外部設備呢?

        如果要讀取用戶機上已知路徑下的文件呢?

        這個時候就要用到ActiveX控件了,掃碼器、讀卡器、高拍儀等外部設備對外提供了ActiveX控件,ActiveX控件對外發布了外設調用接口。瀏覽器只要創建一個控件對象就可以調用接口驅動外設了,具體的實現在後文。


目錄

        1、介紹瀏覽器的“沙箱”安全機制

        2、介紹ActiveX控件

        3、利用VC++6.0開發OCX控件

        4、WEB端調用OCX控件的接口

        5、OCX控件打包發佈


一、沙箱(SandBox)--瀏覽器的一種安全機制

        沙箱是一種隔離對象/線程/進程的機制,控制瀏覽器訪問系統資源的權限,從而達到保護用戶的系統不被網頁上的惡意軟件侵入、保護用戶系統的輸入事件(鍵盤/鼠標)不被監視、保護用戶系統中的文件不被偷取等目的。最初的瀏覽器沙箱是基於Hook實現的,後來的Chrome沙箱是利用操作系統提供的一些安全機制實現的。


二、ActiveX控件

        ActiveX控件是可以在應用程序和網絡中計算機上重複使用的程序對象。ActiveX控件可由不同語言的開發工具開發,包括C++和Visual Basic或PowerBuilder,甚至一些技術性語言如VBScript。

        常用的ActiveX控件由DLL和OCX兩種,其中DLL可以是函數接口,也可以是對象接口,OCX是DLL中的一種純面向對象的控件,一般跨語言都用OCX控件。


三、利用VC++6.0開發OCX控件

        案例:將用戶PC機中已知路徑下的JPG圖片轉成base64字符串返回

        接口:string image2Base64(fullPath)

        說明:輸入圖片文件完整路徑,獲取圖片的base64字符串

第一步:創建項目ImgTools:

        *提示:工程選擇“MFC ActiveX ControlWizard”

1、選擇工程,輸入文件名

        點擊確定:

2、默認配置

        直接點擊完成:

3、完成創建

        點擊確定,項目創建成功,查看FileView目錄:

4、創建項目後,自動生成的文件目錄

第二步:添加base64編碼和解碼用的工具類ZBase64

        查看ClassView目錄,右鍵項目節點,選擇New Class,類的類型選擇Generic Class,類名稱ZBase64

新建工具類ZBase64

        ZBase64類創建成功後,右鍵類節點,選擇Add Member Function,爲這個類,新增兩個方法,分別是編碼和解碼(我們只會用到編碼):

        方法1:函數類型:CString;函數描述:Decode(const char *Data, int DataByte, int &OutByte)

CString ZBase64::Decode(const char *Data, int DataByte, int &OutByte)
{
	//解碼錶  
    const char DecodeTable[] =  
    {  
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
        62, // '+'  
        0, 0, 0,  
        63, // '/'  
        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'  
        0, 0, 0, 0, 0, 0, 0,  
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,  
        13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z'  
        0, 0, 0, 0, 0, 0,  
        26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,  
        39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z'  
    };  
    //返回值  
    CString strDecode;  
    int nValue;  
    int i= 0;  
    while (i < DataByte)  
    {  
        if (*Data != '\r' && *Data!='\n')  
        {  
            nValue = DecodeTable[*Data++] << 18;  
            nValue += DecodeTable[*Data++] << 12;  
            strDecode+=(nValue & 0x00FF0000) >> 16;  
            OutByte++;  
            if (*Data != '=')  
            {  
                nValue += DecodeTable[*Data++] << 6;  
                strDecode+=(nValue & 0x0000FF00) >> 8;  
                OutByte++;  
                if (*Data != '=')  
                {  
                    nValue += DecodeTable[*Data++];  
                    strDecode+=nValue & 0x000000FF;  
                    OutByte++;  
                }  
            }  
            i += 4;  
        }  
        else// 回車換行,跳過  
        {  
            Data++;  
            i++;  
        }  
     }  
    return strDecode;
}

        方法2:函數類型:CString;函數描述:Encode(const char *Data, int DataByte)

CString ZBase64::Encode(const char *Data, int DataByte)
{
    //編碼表  
    const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  
    //返回值  
    CString strEncode;  
    unsigned char Tmp[4]={0};  
    int LineLength=0;  
    for(int i=0;i<(int)(DataByte / 3);i++)  
    {  
        Tmp[1] = *Data++;  
        Tmp[2] = *Data++;  
        Tmp[3] = *Data++;  
        strEncode+= EncodeTable[Tmp[1] >> 2];  
        strEncode+= EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F];  
        strEncode+= EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F];  
        strEncode+= EncodeTable[Tmp[3] & 0x3F];  
        if(LineLength+=4,LineLength==76) {strEncode+="\r\n";LineLength=0;}  
    }  
    //對剩餘數據進行編碼  
    int Mod=DataByte % 3;  
    if(Mod==1)  
    {  
        Tmp[1] = *Data++;  
        strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];  
        strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4)];  
        strEncode+= "==";  
    }  
    else if(Mod==2)  
    {  
        Tmp[1] = *Data++;  
        Tmp[2] = *Data++;  
        strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];  
        strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)];  
        strEncode+= EncodeTable[((Tmp[2] & 0x0F) << 2)];  
        strEncode+= "=";  
    }
    return strEncode;
}

第三步:新增控件對外的接口GetImgBase64:

        這裏有3個文檔需要修改,

        1、ImgTools.odl文檔,添加代碼:[id(1)] BSTR GetImgBase64(BSTR filePath);

ImgTools.odl

        2、ImgToolsCtl.h文檔,添加代碼:

        afx_msg BSTR CImgToolsCtrl::GetImgBase64(LPCTSTR filePath);

        dispidGetImgBase64 = 1L,

ImgToolsCtl.h

        3、ImgTools.cpp文檔,添加代碼:

        DISP_FUNCTION(CImgToolsCtrl, "GetImgBase64", GetImgBase64, VT_BSTR, VTS_BSTR )

ImgTools.cpp p1

        ImgTools.cpp文檔,還需添加該接口的實現

BSTR CImgToolsCtrl::GetImgBase64(LPCTSTR filePath)
{
	CString strResult = "123";
	return strResult.AllocSysString();
}

第四步:實現接口的圖片Base64編碼:

          爲CImgToolsCtrl類新增成員變量ZBase64 zBase;(手動添加時需要在頭文件中加入代碼#include "ZBase64.h")
          爲GetImgBase64接口添加具體的實現代碼:
BSTR CImgToolsCtrl::GetImgBase64(LPCTSTR filePath)
{
	CString strResult;
	FILE * fImg = fopen (filePath, "rb") ;
	if (!fImg)
	{
		strResult = "file is not exist!";
	}
	else
	{
		CString img;
		fseek(fImg,0L,2);
		int sumLen = ftell(fImg);
		rewind(fImg);
		char ch;
		for(int i = 0; i < sumLen; i ++)
		{
			ch=fgetc(fImg);
			img += ch;
		}
		strResult = zBase.Encode(img.GetBuffer(sumLen), sumLen);
		fclose(fImg);
	}
	return strResult.AllocSysString();
}

第五步:組裝控件,從debug文件夾中獲取生成的ocx控件

        上面4步過後,全部保存,然後工具欄->組建->全部重建,即可在項目所在路徑下的debug目錄中看到ocx控件:

OCX目錄


四、WEB端調用OCX控件的接口

第一步:註冊OCX控件

        在ImgTools.ocx同級目錄下,新增reg.bat文件

        文本形式打開reg.bat文件後,輸入一條指令:RegSvr32 ImgTools.ocx

        保存文件後,雙擊reg.bat文件即可成功註冊ImgTools控件:

註冊控件

第二步:編寫測試網頁

    新建testOCX.html文檔,用文本編輯器輸入以下代碼:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
	
	<head>
		<meta charset="utf-8" />
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
		<title>測試OCX</title>
	</head>
	
	<body>
		<object id='ocxObj' name='ocxObj' classid='clsid:130A16C5-5374-4E3D-9071-063FE3AC0205' style='display:none'></object>

		<input type="button" value="測試" onclick="test()" />
		<br/><br/>
		圖片完整路徑:<input type="text" id="path" />
		<br/><br/>
		<textarea rows="8" style="width:700px" id="showMsg">123123</textarea>

		<script type="text/javascript">
			function test() {
				var path = document.getElementById("path").value;
				var str = ocxObj.GetImgBase64(path);
				document.getElementById("showMsg").value = str;
			}
		</script>
	</body>

</html>
        其中“130A16C5-5374-4E3D-9071-063FE3AC0205”是ImgTools.odl文檔中最後一個,即第四個uuid值。

    雙擊testOCX.html文件,用瀏覽器打開後,會提示ActiveX控件,點“是”或者“確定”就行:
    (*注:360瀏覽器用兼容模式)
測試頁面
    輸入我本地圖片的一個路徑“D:\\seal.png”,點擊“測試”按鈕:
測試頁面1
    成功顯示出圖片的base64路徑!
    用java來測試下得到的base64字串是否正確:
java驗證
    OK,完全一樣。

                                                                                                 
以上,第5點的OCX控件的打包部署放在後面再補上!
如果你想要聯繫博主,可以加博主的私人QQ:987031490
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章