文章目錄
當初為了使使用者安全性問題得到保障,伺服器端曾要求各用戶端程式根據機器的唯一標識,經過MD5等演算法得出一個值並傳遞給伺服器。但是找遍了API文檔和MSDN的官方論壇,也沒有找到可以像Windows phone中通過DeviceExtendedProperties.TryGetValue("DeviceUniqueId", out DeviceUniqueID) 可以直接獲得到的機器唯一標識,得到的結果只有一句話:You cannot do that from a Metro app. That is by design.
可能是我們做win8開發的時間比較早吧,後來不知道什麼時候,最近得知有種方法可以得到類似的這個標識:App Specific Hardware ID(ASHWID),就趕快開啟部落格園給大家分享出來。
App Specific Hardware ID(ASHWID),翻譯成中文是: 應用特定硬體ID,對每個應用/程式包來說,得出的 ASHWID 都不同。 除非基本硬體已更改,否則相同應用的兩次調用會導致 ASHWID 相同。 但是,如果裝置的硬體設定檔更改(如,當使用者拔出 USB Bluetooth 適配器時),則 ASHWID 會更改。 後端雲端服務可以驗證 ASHWID 並將其與之前報告的值相比較。 雖然 ASHWID 改變,但可以分析它來檢測變化是否僅由於較小更改(如,系統中記憶體增加)而導致。 變化容差層級由後端雲端服務實現來決定。隨後的部分中提供了組成 ASHWID 的特定元素和如何分析這些元素的指南。
也就是說,在同一台機器上(硬體裝置都沒有變化),不同應用的ASHWID不同,同一應用不同版本的ASHWID相同。在不同機器上同一應用的ASHWID也不同
ASHWID 結構
ASHWID 是根據組成裝置的多個硬體組件而得出的結果。ASHWID 旨在針對每個應用/程式包都刻意不同,以防止出現針對系統範圍的行為並保護使用者隱私。每個組件(如果出現)都對應所返回 ASHIWD 位元組流的一部分。 以下列出了 9 個組件:
- 處理器的 CPU ID
- 記憶體大小
- 磁碟裝置的序號
- 網路介面卡(NIC MAC 位址 - 第一個執行個體)
- 音頻適配器
- 擴充塢
- Bluetooth 地址
- 移動寬頻裝置識別碼
- BIOS
ASHWIDS 樣本
不同組件 ID 的枚舉順序沒有必要連續。以下流顯示少量 ASHWID 樣本。注意,在流中,組件 ID 的數字及其順序會不同。
- 7,0,124,215,3,0,206,143,8,0,128,55,5,0,12,222,5,0,128,255,6,0,1,0,4,0,20,22,4,0,48,155,1,0,250,155,2,0,162,217,9,0,92,101
Samsung Intel Core i5 平板電腦上發現的移動寬頻。
- 7,0,124,215,3,0,206,143,8,0,128,55,5,0,126,129,5,0,12,222,5,0,128,255,6,0,1,0,4,0,20,22,4,0,48,155,4,0,178,193,1,0,250,155,2,0,162,217,9,0,92,101
當靠接時同一裝置上有三個不同音頻適配器和當靠接時同一裝置上有三個不同網路介面卡。
- 3,0,188,97,3,0,76,128,3,0,250,138,5,0,220,130,6,0,1,0,4,0,20,164,1,0,204,49,2,0,226,37,9,0,22,72
案頭上發現三個不同磁碟。
- 3,0,24,211 ,5,0,182,46,5,0,54,49,6,0,1,0,4,0,203,9,1,0,148,99,2,0,162,255,9,0,140,234
Nvidia Tegra 3 裝置。你可能會注意到流“6,0,1,0”與擴充塢對應,不論裝置或板型規格如何。
HardwareIdentification.GetPackageSpecificToken 方法可為 Metro 風格應用提供一種方式來產生運行應用的裝置的 ASHWID。在同一裝置上調用此 API 的兩個應用會返回不同的 ASHWID。 對於給定的應用/程式包,ASHWID 不受以下操作的影響:
- OS 重新安裝
- 推送按鈕重設
- OS SKU 升級
- 應用的版本更新
- 在同一裝置上更改使用者
也就是說,一般情況下,只要硬體沒有變過,ASHWID是不會變的,在一定程度上可以解決無法擷取到唯一標識的問題。
代碼如下:
private string GetUniqueId() { var token = Windows.System.Profile.HardwareIdentification.GetPackageSpecificToken(null); IBuffer buffer = token.Id; using (var dataReader = DataReader.FromBuffer(buffer)) { var bytes = new byte[buffer.Length]; dataReader.ReadBytes(bytes); return BitConverter.ToString(bytes); } }