很多時候都很難琢磨客戶在想什麼,也許是自己業務經驗不足,也許是客戶要顯示出他在軟體方面也非常的專業。記得以前聽過一個故事,說一個富人想娶個媳婦,然後他比較鐘意的有三個女人,然後就想從三個女人中選一個,他分別給了三個女人各一千塊錢,並對她們說,“我這裡有一個房間,請你們用自己的一千塊錢儘可能的將房間填 ...
很多時候都很難琢磨客戶在想什麼,也許是自己業務經驗不足,也許是客戶要顯示出他在軟體方面也非常的專業。記得以前聽過一個故事,說一個富人想娶個媳婦,然後他比較鐘意的有三個女人,然後就想從三個女人中選一個,他分別給了三個女人各一千塊錢,並對她們說,“我這裡有一個房間,請你們用自己的一千塊錢儘可能的將房間填滿”。第一個女人,將1000塊錢都買了棉花,但是這些棉花只填滿了整個房間的三分之一;第二個女人,將1000塊錢都買了氣球,但是這些氣球也只填滿了整個房間的三分之二;第三個女人,花了1塊錢買了一支蠟燭,讓蠟燭的光照亮了整個房間。然後……這個富人愉快的娶了其中胸部最大的那個女人。這個故事告訴我們,有時你根本不知道客戶到底要的是什麼!
解決安全登錄的問題
去給客戶演示系統,演示完剛開發完的系統以後客戶就將我們的系統批的遍體鱗傷,這時才知道自己的系統比想象中的更不堪。在如此不堪的系統面前,客戶又提出了一個需求,要限制用戶的登錄機器。補充一下,演示的系統是一個ERP系統,是BS結構的,用Java寫的。客戶要求,要限制能夠登錄系統的電腦,需要綁定MAC地址。因為系統里的數據比較重要,不能讓員工回家登錄系統,因此必須要進行限制。
解決思路
這樣的問題,能想到的解決思路只有兩個:
1、在EXE文件中嵌入一個瀏覽器控制項,瀏覽器中顯示ERP的頁面,EXE獲取MAC地址後提交到伺服器。感覺這樣先是要處理EXE提交的MAC地址,然後還要和頁面交互,想想貌似比較複雜,就否掉了。
2、寫一個OCX,讓頁面中的JS與OCX進行交互,OCX獲取到MAC地址後,將MAC返回給JS,JS通過DOM操作寫入到對應的表單中,然後和用戶名、密碼一起提交給伺服器。感覺這個好像實現起來還比較簡單。就這個吧!
OCX中獲取MAC地址的關鍵代碼
OCX中可以直接調用Windows操作系統的API函數,寫起來也比較簡單,代碼如下:
1 BSTR CGetMacCtrl::GetMacAddress(void) 2 { 3 AFX_MANAGE_STATE(AfxGetStaticModuleState()); 4 5 CString strResult; 6 7 // TODO: 在此添加調度處理程式代碼 8 ULONG outBufLen = sizeof(IP_ADAPTER_ADDRESSES); 9 PIP_ADAPTER_ADDRESSES pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(outBufLen); 10 if (pAddresses == NULL) 11 { 12 return NULL; 13 } 14 // Make an initial call to GetAdaptersAddresses to get the necessary size into the ulOutBufLen variable 15 if(GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW) 16 { 17 free(pAddresses); 18 pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(outBufLen); 19 if (pAddresses == NULL) 20 { 21 return NULL; 22 } 23 } 24 25 wchar_t acMAC[32] = { 0 }; 26 27 if(GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAddresses, &outBufLen) == NO_ERROR) 28 { 29 // If successful, output some information from the data we received 30 for(PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddresses; pCurrAddresses != NULL; pCurrAddresses = pCurrAddresses->Next) 31 { 32 // 確保MAC地址的長度為 00-00-00-00-00-00 33 if(pCurrAddresses->PhysicalAddressLength != 6) 34 { 35 continue; 36 } 37 wsprintf((LPWSTR)acMAC, _T("%02X-%02X-%02X-%02X-%02X-%02X"), 38 int (pCurrAddresses->PhysicalAddress[0]), 39 int (pCurrAddresses->PhysicalAddress[1]), 40 int (pCurrAddresses->PhysicalAddress[2]), 41 int (pCurrAddresses->PhysicalAddress[3]), 42 int (pCurrAddresses->PhysicalAddress[4]), 43 int (pCurrAddresses->PhysicalAddress[5])); 44 break; 45 } 46 } 47 48 free(pAddresses); 49 strResult = acMAC; 50 51 return strResult.AllocSysString(); 52 }
代碼差不多就這樣吧,我用的VS2012寫的ActiveX,編譯生成OCX。
在Web中進行測試
在Web中測試也比較簡單,通過clsid引入OCX文件,然後JS調用OCX文件中的函數,函數返回MAC地址給JS,JS進行DOM操作,代碼如下:
1 <!DOCTYPE html> 2 <html lang="zh-CN"> 3 <head> 4 <meta charset="utf8"> 5 <title>獲取Mac地址Demo</title> 6 </head> 7 <body> 8 <object id="getmac" classid="clsid:52931A6A-93B4-4750-8FE6-B666E90B1D54" 9 codebase="'getmac.ocx'" style="display:none"></object> 10 11 <h1>MAC:</h1> 12 <span id="mac"></span> 13 <input type="text" id="macAddress" name="macAddress" value="" /> 14 </body> 15 <script> 16 var mac = getmac.GetMacAddress(); 17 document.getElementById("mac").innerHTML = mac; 18 document.getElementById("macAddress").value = mac; 19 document.getElementById("macAddress").style.display = ''; 20 </script> 21 </html>
通過object標簽引入了OCX文件,定義了id為getmac,然後通過getmac來調用OCX中的函數GetMacAddress()獲取MAC地址。
經過簡單的測試還是可以的,然後我整合進入了JeeSite系統中(我其他文章說過,我們的項目是在JeeSite上做二次開發),測試以後發現ERP的頁面對IE瀏覽器支持不好。因為OCX只能在IE瀏覽器中使用,結果這個方案就放棄了。後來,找到一個開源的Chrome的插件,也完成MAC地址的獲取,該Chrome插件分為兩部分,一部分是Chrome的插件,另外一個是EXE文件,該EXE文件也是與插件進行通信的,由於該插件不是我寫的,我就不往這裡放了。總之,最好還是把客戶端這個需求解決了。OCX的方法就留在這裡吧!也許,我以後會用到也說不定呢。