navigator.mediaDevices.enumerateDevices() tiết lộ số lượng, ID và nhãn thiết bị trước khi bạn cấp quyền camera hay micro. Kẻ theo dõi khai thác nó ra sao.
Mọi laptop có webcam và micro tích hợp, mọi máy tính để bàn cắm tai nghe USB, mọi điện thoại có hai camera — tất cả đều hiện ra với một trang web chỉ qua một lệnh gọi API âm thầm. navigator.mediaDevices.enumerateDevices() ban đầu được thiết kế để trang web liệt kê các camera và micro khả dụng trước khi bắt đầu cuộc gọi video. Nó làm tốt việc đó, nhưng đồng thời cũng trao đi một tín hiệu vân tay không cần bất kỳ lời nhắc quyền nào, và tín hiệu đó càng phong phú hơn ngay khi người dùng thực sự cấp quyền camera hoặc micro.
Điểm chính
enumerateDevices()chạy mà không cần bất kỳ lời nhắc quyền nào và trả về số lượng cùng loại thiết bị âm thanh/video đã kết nối cho bất kỳ trang nào gọi nó.- Trước khi được cấp quyền,
deviceIdvàlabeltrống, nhưng số lượng và loại thiết bị (bao nhiêu camera, micro, loa) vẫn thêm entropy. - Sau khi được cấp quyền (dù chỉ một lần, cho bất kỳ trang nào),
deviceId,groupIdvà chuỗilabeldễ đọc — thường bao gồm cả tên model phần cứng — trở nên hiển thị. groupIdliên kết các thiết bị dùng chung một phần cứng vật lý, cho phép script suy ra, chẳng hạn, một camera và micro đến từ cùng một webcam.- Chỉ riêng số lượng thiết bị đã là một tín hiệu xuyên trang có ý nghĩa: hầu hết máy tính để bàn báo cáo một tập thiết bị nhỏ, ổn định, duy trì qua nhiều phiên duyệt web và thậm chí qua cả việc khởi động lại trình duyệt.
enumerateDevices() trả về gì
Phương thức MediaDevices.enumerateDevices(), một phần của đặc tả Media Capture and Streams, trả về một promise phân giải thành một mảng đối tượng MediaDeviceInfo — mỗi đối tượng ứng với một thiết bị đầu vào âm thanh, đầu ra âm thanh, hoặc đầu vào video mà hệ điều hành cho trình duyệt thấy. Mỗi đối tượng mang bốn trường:
kind—"audioinput","audiooutput", hoặc"videoinput"deviceId— một định danh mờ đục, giới hạn theo nguồn gốc, cho thiết bịgroupId— một định danh mờ đục, dùng chung cho các thiết bị thuộc cùng một phần cứng vật lýlabel— tên thiết bị dễ đọc, chẳng hạn "FaceTime HD Camera" hoặc "Logitech BRIO"
Quan trọng là, bản thân lệnh gọi này không cần quyền camera hay micro — chỉ getUserMedia() mới cần. Một trang có thể gọi enumerateDevices() ngay khi tải, trước khi người dùng tương tác với bất cứ thứ gì, và lập tức biết được máy có bao nhiêu thiết bị âm thanh và video.
Khác biệt trước và sau khi cấp quyền
Đặc tả cố ý để trống deviceId, groupId và label cho đến khi nguồn gọi đã được cấp quyền truy cập camera hoặc micro ít nhất một lần — đây là nhượng bộ của các nhà sản xuất trình duyệt trước rủi ro vân tay. Nhưng việc để trống này chỉ là một phần, không phải toàn bộ, và chính khoảng cách giữa hai trạng thái đó cũng mang tính thông tin.
async function getMediaDeviceFingerprint() {
const devices = await navigator.mediaDevices.enumerateDevices();
const counts = { audioinput: 0, audiooutput: 0, videoinput: 0 };
const labeled = [];
for (const d of devices) {
counts[d.kind]++;
if (d.label) {
// Chỉ được điền sau khi getUserMedia() đã được cấp quyền ít nhất một lần
labeled.push({ kind: d.kind, groupId: d.groupId, label: d.label });
}
}
return { counts, total: devices.length, labeled };
}
Trước khi cấp quyền: mọi deviceId và label đều là chuỗi rỗng, nhưng devices.length và số lượng theo từng kind là chính xác. Một máy có một micro tích hợp, một camera tích hợp, và một tai nghe Bluetooth đã ghép nối sẽ báo cáo khác với một laptop trần trụi không có gì gắn thêm — và con số đó ổn định trên mọi trang mà người dùng truy cập, đóng vai trò một tín hiệu xuyên trang có cardinality thấp nhưng bền bỉ.
Sau khi cấp quyền: nhãn và ID được điền ngay lập tức, và chúng thường tiết lộ nhiều hơn một cái tên chung chung. Chuỗi nhà sản xuất và model ("Logitech BRIO", "iPhone Microphone") khá phổ biến, và giá trị deviceId vẫn ổn định cho nguồn đó qua nhiều phiên — về bản chất trở thành một định danh bán bền vững giới hạn theo trang, tương tự cách ID khách truy cập bền vững sống sót qua việc xóa bộ nhớ đệm nhờ các tín hiệu ổn định khác.
groupId: liên kết phần cứng vật lý
groupId tồn tại để ứng dụng có thể tránh chọn một micro và một loa gây phản hồi âm thanh vì chúng là cùng một thiết bị vật lý — nhưng nó cũng đóng vai trò khóa tương quan. Hai mục MediaDeviceInfo cùng chia sẻ một groupId chắc chắn đến từ cùng một phần cứng, cho phép script suy luận những điều như "camera này và micro này là cùng một webcam USB" mà không cần đọc bất kỳ chuỗi model nào. Kết hợp với số lượng thiết bị và bất kỳ nhãn nào có sẵn, groupId thu hẹp dấu vân tay bằng cách loại trừ các tổ hợp thiết bị không thể tồn tại cùng nhau về mặt vật lý.
Số lượng thiết bị như một tín hiệu xuyên trang
Việc liệt kê thiết bị khá khác thường trong số các kỹ thuật vân tay ở chỗ nó không cần pipeline kết xuất, không cần GPU, và không cần đo thời gian — nó là một phép đọc trực tiếp, có cấu trúc, về danh mục phần cứng vật lý. Kết hợp với các tín hiệu như đầu ra WebGL và Canvas, số lượng thiết bị đa phương tiện thêm một trục độc lập khác: hai khách truy cập có cùng GPU và cùng hash Canvas vẫn có thể được phân biệt nếu một người có loa màn hình ngoài và mảng micro webcam mà người kia không có. Đây chính là nguyên lý tổ hợp được nêu trong hướng dẫn về vân tay trình duyệt của chúng tôi — không tín hiệu đơn lẻ nào mang tính quyết định, nhưng các tín hiệu độc lập nhân lên với nhau.
Nó cũng tương tác với WebRTC theo một cách đáng chú ý: các trang đã yêu cầu quyền camera/micro cho một tính năng hợp pháp (gọi video, ghi âm) sẽ nhận được danh sách thiết bị có nhãn đầy đủ "miễn phí", biến một lần cấp quyền chức năng thành một đóng góp vân tay bền bỉ và bất thường chi tiết.
Biện pháp giảm thiểu
- Từ chối quyền camera/micro theo mặc định và chỉ cấp theo từng trang khi bạn thực sự định dùng tính năng đó — điều này giữ
deviceIdvàlabeltrống trên các trang không cần chúng. - Các tùy chọn
media.navigator.enabledcủa Firefox và liên quan, cùng các trình duyệt riêng tư xây dựng trên nguyên lý đồng nhất (Tor Browser), hạn chế hoặc chặn hoàn toàn việc liệt kê đối với hầu hết các nguồn — với cái giá là phá vỡ các tính năng gọi WebRTC hợp pháp. - Trình quản lý quyền của trình duyệt — xem lại và thu hồi các quyền camera/micro cũ (
chrome://settings/content/cameravà tương đương trên Firefox/Safari) thu hẹp tập hợp nguồn có thể thấy thiết bị có nhãn. - Rút phích các thiết bị ngoại vi không dùng đến giảm entropy từ số lượng thiết bị, dù điều này không thực tế với hầu hết mọi người và chỉ đóng lại một trục trong số nhiều trục.
Không biện pháp nào trong số này đóng hoàn toàn tín hiệu số lượng thiết bị trước khi cấp quyền, vì chặn hoàn toàn enumerateDevices() sẽ phá vỡ bất kỳ trang nào cần cung cấp bộ chọn thiết bị — mục tiêu thực tế là hạn chế có bao nhiêu nguồn đạt đến trạng thái phong phú hơn sau khi cấp quyền.
Để xem trình duyệt của chính bạn đang tiết lộ những tín hiệu vân tay nào — Canvas, WebGL, phông chữ và hơn thế nữa — hãy chạy công cụ kiểm tra vân tay của BrowserInsight và đánh giá chúng khiến bạn dễ nhận diện đến mức nào.
Câu hỏi thường gặp
enumerateDevices() có cần quyền camera hoặc micro không?
Không. Bản thân lệnh gọi hoạt động mà không cần bất kỳ lời nhắc nào và trả về ngay số lượng cùng loại thiết bị. Chỉ các trường deviceId, groupId và label mới cần quyền getUserMedia() trước đó từ nguồn đó để được điền.
Một trang web có thể biết tôi có bao nhiêu camera hoặc micro mà không cần hỏi không?
Có. devices.length và phân tích theo kind khả dụng trước khi bất kỳ hộp thoại quyền nào xuất hiện, và chúng duy trì qua các lần truy cập vì chúng phản ánh phần cứng đã kết nối, chứ không phải thứ mà người dùng có thể đặt lại bằng cách xóa cookie.
Xóa cookie có đặt lại vân tay thiết bị đa phương tiện của tôi không?
Không. Số lượng thiết bị, và một khi đã được cấp quyền, các giá trị deviceId/groupId, đều bắt nguồn từ phần cứng và trạng thái quyền theo từng nguồn, chứ không phải từ bộ nhớ lưu trữ mà việc xóa cookie sẽ loại bỏ — tương tự cách vân tay Canvas và WebGL trong hướng dẫn về vân tay trình duyệt sống sót qua việc xóa bộ nhớ đệm.
Vân tay thiết bị đa phương tiện đã được sử dụng trên các trang web thực chưa?
Các thư viện vân tay thường đưa số lượng thiết bị vào như một trong nhiều tín hiệu, và bất kỳ trang nào có tính năng gọi video hoặc ghi âm hợp pháp đều đã có quyền truy cập danh sách có nhãn đầy đủ một khi quyền được cấp, bất kể trang đó có dùng dữ liệu đó để theo dõi hay không.

