Lấy dấu vân tay bố cục bàn phím đọc bố cục phím vật lý qua getLayoutMap() — tín hiệu âm thầm, chỉ có trên Chromium, gợi ý khu vực và hiếm khi thay đổi.
Lấy dấu vân tay bố cục bàn phím đọc một tín hiệu mà hầu hết mọi người chưa từng nghĩ tới: bố cục vật lý mà bàn phím của bạn được cấu hình để dùng, được bộc lộ qua phương thức getLayoutMap() của Keyboard API. Một trang web có thể, về bản chất, hỏi "phím vật lý này tạo ra ký tự gì?" — và câu trả lời sẽ tiết lộ bố cục ở cấp hệ điều hành của bạn (QWERTY, AZERTY, QWERTZ, JIS và hàng chục bố cục khác) mà không cần xin bất kỳ quyền nào. Bài viết này giải thích cách API hoạt động, vì sao bố cục vật lý lại để lộ khu vực địa lý và ngôn ngữ, và điều gì thực sự giới hạn tính hữu dụng của nó như một tín hiệu theo dõi.
Tóm tắt nhanh
navigator.keyboard.getLayoutMap()trả về một ánh xạ từ mã phím vật lý (như"KeyQ") sang ký tự mà bố cục của bạn tạo ra ở vị trí đó ("q"trên QWERTY,"a"trên AZERTY).- Bố cục vật lý tương quan với khu vực và ngôn ngữ — AZERTY phổ biến ở Pháp, QWERTZ là chuẩn ở Đức/Áo/Thụy Sĩ, JIS chỉ dùng ở Nhật Bản — bổ sung một tín hiệu độc lập với
navigator.languagehay múi giờ. - API này chỉ được triển khai trên các trình duyệt nền Chromium ở máy tính để bàn (Chrome 69 trở lên, Edge, Opera); Firefox và Safari hoàn toàn không cung cấp nó, và bản đặc tả cũng không kỳ vọng thiết bị di động hỗ trợ — nên nó vô dụng với một phần lớn khách truy cập.
- Nó không hiển thị bất kỳ hộp thoại xin quyền nào cho người dùng; giới hạn duy nhất là yêu cầu ngữ cảnh an toàn (HTTPS) và tính năng Permissions Policy
keyboard-mapvới danh sách cho phép mặc định làself— tức một công tắc nằm trong tay chính trang web, hoàn toàn khác với sự đồng ý của người dùng. - Vì việc thay đổi bố cục bàn phím ở cấp hệ thống là một hành động có chủ đích và hiếm khi xảy ra, giá trị này ổn định bất thường qua các phiên so với những tín hiệu như độ phân giải màn hình hay kích thước cửa sổ.
Lấy dấu vân tay bố cục bàn phím là gì?
Lấy dấu vân tay bố cục bàn phím là việc dùng Keyboard API để xác định bố cục phím vật lý mà hệ điều hành đang sử dụng, rồi đưa giá trị đó vào một định danh thiết bị hoặc trình duyệt. Đây chỉ là một lệnh gọi API nhỏ, nhưng nó bổ sung một tín hiệu mà các kỹ thuật lấy dấu vân tay khác chưa bao phủ: hầu hết các bộ công cụ lấy dấu vân tay đọc phần cứng dựng hình (canvas, WebGL), phần mềm đã cài (phông chữ), hoặc các tùy chọn do trình duyệt báo cáo (navigator.language, múi giờ) — không cái nào phản ánh trực tiếp cách bàn phím vật lý của bạn được kết nối với hệ điều hành.
Khác với lấy dấu vân tay bằng phông chữ hay canvas, kỹ thuật này không dựa trên việc suy luận qua sự khác biệt khi dựng hình. getLayoutMap() là một API được thiết kế riêng cho mục đích này, trả về trực tiếp thông tin bố cục — đó cũng chính là lý do nó đáng để tìm hiểu riêng.
Bên trong getLayoutMap(): nó trả về gì
getLayoutMap() trả về một Promise phân giải thành một KeyboardLayoutMap — một đối tượng chỉ đọc, giống Map. Khóa của nó là mã (code) của phím vật lý, lấy từ tập giá trị code chuẩn, xác định một phím theo vị trí của nó trên bàn phím bất kể chữ in trên phím đó là gì ("KeyQ" luôn là phím ngay bên phải phím Tab, bất kể bố cục nào). Giá trị của nó là ký tự mà bố cục hiện tại của bạn tạo ra ở vị trí đó.
// Đọc ký tự mà mỗi phím vật lý tạo ra theo bố cục hiện tại
async function getKeyboardLayoutSignal() {
if (!navigator.keyboard?.getLayoutMap) return null; // Firefox, Safari: không hỗ trợ
const layoutMap = await navigator.keyboard.getLayoutMap();
const probeCodes = ['KeyQ', 'KeyW', 'KeyA', 'KeyY', 'KeyZ', 'Semicolon', 'BracketLeft'];
// Trên QWERTY: KeyQ -> "q". Trên AZERTY: KeyQ -> "a", KeyW -> "z", KeyA -> "q".
return probeCodes.map((code) => layoutMap.get(code) ?? null).join(',');
}
Sự khác biệt giữa mã (vị trí vật lý) và phím (ký tự tạo ra) chính là điều khiến tín hiệu này có thể dùng để lấy dấu vân tay: hai khách truy cập có phần cứng giống hệt nhau và phiên bản trình duyệt giống hệt nhau vẫn có thể trả về những chuỗi khác nhau cho cùng một phép dò, đơn giản chỉ vì cài đặt bố cục bàn phím ở cấp hệ điều hành của họ khác nhau. Chỉ cần dò một vài mã có sự khác biệt lớn nhất giữa QWERTY, AZERTY và QWERTZ (các phím chữ cái) là đủ để phân loại một khách truy cập vào một nhóm bố cục cụ thể chỉ với rất ít mã.
Vì sao bố cục vật lý lại để lộ khu vực và ngôn ngữ
Các bố cục bàn phím không phân bố đồng đều — chúng tập trung chặt chẽ theo quốc gia và cộng đồng ngôn ngữ:
- QWERTY chiếm ưu thế ở Mỹ, Anh và hầu hết các khu vực nói tiếng Anh (với biến thể Anh hoán đổi một vài phím dấu câu).
- AZERTY là bố cục mặc định ở Pháp và Bỉ.
- QWERTZ là chuẩn trên khắp Đức, Áo và Thụy Sĩ.
- Các bố cục JIS đặc trưng cho Nhật Bản; ЙЦУКЕН dùng ở Nga và các quốc gia dùng chữ Kirin khác.
Chính sự tập trung đó khiến tín hiệu này có giá trị với một bên theo dõi: nó là một chỉ dấu thay thế cho khu vực, độc lập với định vị địa lý theo IP và độc lập với tiêu đề Accept-Language hay navigator.language — hai thứ mà một người dùng chú trọng quyền riêng tư có thể đã ghi đè từ trước. Một khách truy cập tuyên bố IP ở Mỹ và navigator.language là tiếng Anh, nhưng lại báo cáo bố cục AZERTY, là một sự mâu thuẫn đáng được đánh dấu — cùng logic mà danh sách tự kiểm tra tính nhất quán dấu vân tay của chúng tôi áp dụng cho sự không khớp giữa GPU/hệ điều hành cũng áp dụng ở đây cho sự không khớp giữa ngôn ngữ và bố cục. Xét riêng lẻ, bố cục là một tín hiệu thô, entropy thấp — trên toàn thế giới chỉ có vài chục bố cục phổ biến — nhưng khi kết hợp với các thuộc tính khác, nó thu hẹp thêm đám đông mà một khách truy cập có thể hòa lẫn vào.
Hỗ trợ trình duyệt và mô hình cấp quyền
Phạm vi thực tế của kỹ thuật này bị giới hạn bởi nơi API thực sự tồn tại:
| Trình duyệt | Hỗ trợ getLayoutMap() | Hộp thoại hiển thị cho người dùng |
|---|---|---|
| Chrome / Edge / Opera trên máy tính (Chromium) | Có (Chrome 69 trở lên) | Không |
| Chromium trên di động | Thường không có, hoặc trả về ánh xạ rỗng | Không áp dụng |
| Firefox | Chưa triển khai | Không áp dụng |
| Safari | Chưa triển khai | Không áp dụng |
Có ba điều đáng chú ý. Thứ nhất, đây là tín hiệu độc quyền của Chromium — một script theo dõi dựa vào nó sẽ âm thầm nhận undefined trên Firefox và Safari, nên nó chỉ có thể lấy dấu vân tay được một phần lưu lượng truy cập của web.
Thứ hai, trên điện thoại phạm vi còn hẹp hơn nữa. Đặc tả WICG keyboard-map nói thẳng rằng vì thiết bị di động thường không có bàn phím vật lý nên API này "thường sẽ không hiện diện hoặc không được hỗ trợ trên thiết bị di động", và một nền tảng di động nếu có triển khai thì vẫn có thể trả về ánh xạ bố cục không chứa mục nào. Với một lượng độc giả chủ yếu dùng điện thoại, điều đó loại bỏ phần lớn số người mà kỹ thuật này lẽ ra có thể phân nhóm — và đó là một lý do lớn khiến nó mãi chỉ là tín hiệu bổ trợ chứ không phải tín hiệu cốt lõi.
Thứ ba, ở nơi được hỗ trợ, không có hộp thoại xin đồng ý nào giống như những gì camera, micro hay định vị địa lý kích hoạt. API chỉ yêu cầu ngữ cảnh an toàn (HTTPS) và sự cho phép của tính năng Permissions Policy tên keyboard-map, vốn có danh sách cho phép mặc định là self. Giá trị mặc định đó đáng để đọc kỹ: script của chính trang có thể gọi thoải mái, còn <iframe> khác nguồn gốc sẽ nhận SecurityError trừ khi trang nhúng cấp quyền rõ ràng bằng allow="keyboard-map". Nói cách khác, đây là ranh giới do nhà vận hành trang web vạch ra giữa họ và nội dung họ nhúng, chứ không phải thứ đi hỏi khách truy cập. Từ góc nhìn của người dùng, lệnh gọi này diễn ra âm thầm: không biểu tượng, không hộp thoại, không cách nào nhận biết nó đã xảy ra. Ngược lại, phương thức liên quan keyboard.lock() chỉ giới hạn trong các phiên toàn màn hình và trò chơi — đây là một tính năng khác, với mô hình đe dọa khác, không phải rào cản đối với getLayoutMap(). API này hiện vẫn được ghi nhận là một tính năng thử nghiệm, chưa đạt Baseline — đó chính xác là lý do vì sao sự hỗ trợ trên các trình duyệt vẫn chưa mở rộng.
Tính ổn định: vì sao tín hiệu này hầu như không thay đổi
Hầu hết các thuộc tính dấu vân tay đều trôi dạt theo thời gian: bạn cắm thêm màn hình thứ hai và độ phân giải màn hình thay đổi; bạn cài một phông chữ mới và danh sách phông chữ tăng lên; một bản cập nhật trình duyệt chỉnh sửa đôi chút chuỗi User-Agent. Bố cục bàn phím tĩnh một cách bất thường so với những điều đó. Việc thay đổi bố cục ở cấp hệ điều hành đòi hỏi phải mở cài đặt hệ thống và chủ động chuyển đổi — điều mà đại đa số người dùng chưa bao giờ làm, vì nó gắn liền với bàn phím vật lý mà họ dùng hằng ngày. Chính sự ổn định đó khiến tín hiệu này hấp dẫn như một tín hiệu bổ trợ: dù script chỉ kiểm tra nó thỉnh thoảng, giá trị ghi lại từ tháng trước gần như chắc chắn vẫn đúng cho đến hôm nay — khác hẳn với nhiễu canvas mà một trình duyệt chú trọng quyền riêng tư có thể xoay vòng theo từng phiên.
Vị trí của nó trong bức tranh toàn cảnh
Lấy dấu vân tay bố cục bàn phím là một đóng góp nhỏ so với canvas, WebGL hay phông chữ, nhưng nó minh họa một khuôn mẫu đáng để nhận ra: các trình duyệt liên tục bộc lộ những API hẹp, chuyên dụng (thiết bị đa phương tiện, giọng đọc tổng hợp giọng nói, thông tin mạng), mỗi cái để lộ một mẩu nhỏ dữ liệu thiết bị hoặc khu vực, không có hộp thoại xin quyền riêng. Không cái nào mang tính quyết định khi đứng một mình; nhưng khi cộng dồn lại, chúng tích lũy. Hướng dẫn toàn diện về lấy dấu vân tay trình duyệt của chúng tôi trình bày cách các tín hiệu này kết hợp với nhau, còn lấy dấu vân tay bằng phông chữ là một kỹ thuật gần gũi — cả hai đều nhắm vào Chromium và các trình duyệt khác mà không có bất kỳ yêu cầu hiển thị nào, và cả hai đều mạnh nhất khi là một trong nhiều đầu vào chứ không phải một định danh độc lập.
Cách giảm thiểu
- Dùng một trình duyệt không triển khai API này. Firefox và Safari đơn giản là không cung cấp
getLayoutMap(), nên khách truy cập trên các trình duyệt đó không bị ảnh hưởng bởi kỹ thuật cụ thể này, bất kể các thiết lập khác ra sao. - Trên Chromium, thu hẹp những gì script có thể âm thầm chạm tới. Một tiện ích mở rộng chặn được script theo dõi của bên thứ ba trước khi chúng kịp chạy sẽ xóa luôn điểm gọi — nhưng hãy chọn lọc, vì một tiện ích mở rộng có quyền truy cập rộng tự nó đã là một kênh theo dõi; xem rủi ro quyền riêng tư của tiện ích mở rộng trình duyệt trước khi cài đặt bất cứ thứ gì. Nếu bạn không chỉ là người truy cập mà còn vận hành trang web của riêng mình,
Permissions-Policy: keyboard-map=()sẽ tắt tính năng này cho trang của bạn và mọi thứ được nhúng trong đó. - Đừng chỉ dựa vào việc giấu cài đặt ngôn ngữ. Giả mạo
navigator.languagehay khu vực mà IP thể hiện, trong khi vẫn giữ nguyên bố cục bàn phím thật, sẽ tạo ra chính sự mâu thuẫn mà tín hiệu này giỏi phát hiện — sự nhất quán trên toàn bộ các tín hiệu của bạn quan trọng hơn việc giấu riêng lẻ một tín hiệu nào đó. - Hiểu rõ giới hạn. Cũng như lấy dấu vân tay phông chữ và canvas, đây là tín hiệu ở cấp dựng hình/API, không phải dữ liệu được lưu trữ — chế độ ẩn danh/riêng tư không thay đổi nó, vì đơn giản là chẳng có gì để xóa.
Câu hỏi thường gặp
Lấy dấu vân tay bố cục bàn phím có cần bất kỳ quyền nào không?
Không. getLayoutMap() chỉ yêu cầu ngữ cảnh an toàn (HTTPS) và tính năng Permissions Policy keyboard-map — vốn mặc định đã được cho phép với chính nguồn gốc của trang, và có thể bị tắt bằng tiêu đề của chính trang web. Cả hai đều không hiển thị hộp thoại xin đồng ý cho khách truy cập. Nó âm thầm theo đúng thiết kế.
Những trình duyệt nào có thể bị lấy dấu vân tay theo cách này?
Chỉ các trình duyệt nền Chromium trên máy tính để bàn — Chrome (từ phiên bản 69), Edge, Opera và những trình duyệt khác dựng trên cùng một nhân. Firefox và Safari chưa triển khai getLayoutMap(), nên kỹ thuật này hoàn toàn không áp dụng được với người dùng của chúng; còn với thiết bị di động thì ngay cả bản đặc tả cũng không kỳ vọng có hỗ trợ.
Bố cục bàn phím của tôi có giống với ngôn ngữ gõ của tôi không?
Không hẳn. Bố cục là thiết lập cấp hệ thống gắn với bàn phím vật lý; bạn có thể gõ một ngôn ngữ nào đó bằng một bố cục khác với bố cục "gốc" của quốc gia nói ngôn ngữ đó, dù hầu hết mọi người không làm vậy. Đó chính xác là lý do bố cục hữu ích như một tín hiệu bổ sung, chứ không phải bản sao của navigator.language.
Chỉ riêng tín hiệu này có thể nhận diện được tôi không?
Không — trên toàn thế giới chỉ có vài chục bố cục phổ biến, nên tự thân nó là một tín hiệu entropy thấp. Nó chỉ trở nên có ý nghĩa khi kết hợp với các thuộc tính dấu vân tay khác, hoặc khi nó mâu thuẫn với các tín hiệu khu vực khác mà bạn đã báo cáo.
Làm sao để kiểm tra trình duyệt của tôi đang để lộ những gì?
Chạy công cụ kiểm tra dấu vân tay của BrowserInsight để xem đầy đủ các tín hiệu mà trình duyệt của bạn để lộ, bao gồm cả việc các giá trị bạn báo cáo có khớp với nhau hay không.
Kết luận
Lấy dấu vân tay bố cục bàn phím là một lệnh gọi API nhỏ và âm thầm, biến một thiết lập hệ thống mà gần như không ai để ý thành một tín hiệu tương quan với khu vực, không cần quyền — và nó ổn định bất thường vì việc thay đổi nó đòi hỏi nỗ lực chủ động. Nó chỉ giới hạn ở các trình duyệt Chromium trên máy tính để bàn và tự thân mang entropy thấp, nhưng đây là một ví dụ rõ ràng cho thấy các API hẹp, chuyên dụng của trình duyệt cứ tiếp tục cộng dồn: mỗi API để lộ một chút, không cái nào lên tiếng hỏi — và cộng lại, chúng thu hẹp đám đông mà một khách truy cập có thể hòa lẫn vào.
Muốn thấy cả bộ tín hiệu chứ không chỉ riêng một cái? Hãy chạy công cụ kiểm tra dấu vân tay miễn phí — nó đọc các thuộc tính mà trình duyệt của bạn trao ra ngoài và chỉ cho bạn thấy chỗ nào chúng khớp với nhau, chỗ nào thì không.
Bài viết nên đọc:


