getClientRects() và getBoundingClientRect() để lộ khác biệt bố cục dưới-pixel dùng để lấy dấu vân tay thiết bị — không cần đụng đến canvas.
Mọi phần tử trên trang đều có vị trí và kích thước mà JavaScript có thể đọc chính xác đến một phần nhỏ của pixel. Yêu cầu trình duyệt trả về hình chữ nhật chính xác mà một tiêu đề chiếm giữ, bạn sẽ nhận lại những con số dấu phẩy động như 312.234375 — độ chính xác mà mắt người chẳng bao giờ dùng đến, được tạo ra bởi việc hinting phông chữ, khử răng cưa dưới-pixel, và cách dàn trang văn bản đặc thù theo nền tảng. Những con số này khác nhau đôi chút giữa các thiết bị, và một script đo đủ nhiều giá trị như vậy có thể biến bố cục trang thông thường thành một tín hiệu theo dõi — không cần một phần tử canvas nào, không cần đọc một pixel nào.
Tóm tắt nhanh
getClientRects()vàgetBoundingClientRect()trả về giá trịDOMRectvới độ chính xác dưới-pixel (số thực) — độ chính xác này thay đổi theo cách kết xuất phông chữ, tỷ lệ DPI, và bộ máy dàn trang văn bản của hệ điều hành.- Đo hình chữ nhật của văn bản đã kết xuất là một kiểu lấy dấu vân tay dựa trên bố cục: không cần phần tử
<canvas>, không cần đọc pixel, không cần lời nhắc xin quyền nào — nên nó lách qua được các biện pháp phòng vệ nhắm riêng vào canvas. - Kỹ thuật này có tương quan với — nhưng không giống hệt — lấy dấu vân tay canvas, vì cả hai đều bắt nguồn từ khác biệt trong phông chữ và pipeline kết xuất; kết hợp cả hai cho độ tin cậy cao hơn từng cái riêng lẻ.
- Các trình duyệt anti-detect như GoLogin và Dolphin{anty} đều có công tắc giả mạo "Rects" riêng — một sự thừa nhận ngầm từ ngành anti-detect rằng tín hiệu này thực sự bị kiểm tra trong thực tế.
- Công cụ kiểm tra dấu vân tay của BrowserInsight hiển thị song song các tín hiệu bố cục và canvas mà trình duyệt của bạn đang để lộ.
getClientRects() thực sự trả về gì
getClientRects() và phiên bản đơn giản hơn của nó, getBoundingClientRect(), là những API bố cục thông thường, được chuẩn hóa trong đặc tả CSSOM View Module. Chúng tồn tại để JavaScript có thể trả lời những câu hỏi thường ngày như "phần tử này hiện có đang hiển thị trong viewport không?" hay "dòng văn bản bị ngắt này kết thúc chính xác ở đâu?". Không có gì trong chúng trông giống một công cụ theo dõi.
Gọi getBoundingClientRect() trên bất kỳ phần tử nào, bạn nhận về một DOMRect duy nhất — top, left, width, height cùng các cạnh được suy ra từ đó — mô tả hộp bao quanh phần tử tương đối so với viewport. Gọi getClientRects() thay vào đó, bạn nhận về cả một danh sách hình chữ nhật, mỗi cái ứng với một line box, điều này quan trọng với nội dung inline: một câu bị ngắt thành ba dòng sẽ trả về ba hình chữ nhật riêng biệt, mỗi cái có tọa độ của riêng nó. Range.getClientRects() làm điều tương tự với một vùng chọn văn bản bất kỳ, cho phép script đo một đoạn ký tự cụ thể thay vì cả phần tử.
Các giá trị trả về không phải số nguyên. Chúng là số thực dấu phẩy động độ chính xác kép, bởi engine bố cục của trình duyệt định vị văn bản bằng phép tính dưới-pixel, dù màn hình của bạn cuối cùng vẫn làm tròn mọi thứ về pixel vật lý. Độ chính xác dư ra đó — phần dư thập phân không bao giờ được kết xuất giống hệt nhau trên các thiết bị khác nhau — chính là toàn bộ cơ sở của kiểu lấy dấu vân tay này.
Vì sao các con số khác nhau giữa các thiết bị
Nếu hai trình duyệt kết xuất cùng một HTML với cùng một CSS, tại sao hình chữ nhật lại khác nhau? Giữa "đây là một đoạn văn bản" và "đây là pixel cuối cùng của nó" có vài tầng, mỗi tầng đều tạo ra một biến thiên nhỏ, có thể tái lập:
- Hinting và shaping phông chữ. Engine tạo hình văn bản của hệ điều hành — DirectWrite trên Windows, Core Text trên macOS, FreeType/HarfBuzz trên Linux — quyết định chính xác cách các đường viền glyph được gắn vào lưới pixel. Các quy tắc hinting khác nhau tạo ra advance width khác nhau cho cùng một chuỗi trong cùng một phông.
- Tỷ lệ pixel thiết bị. Màn hình HiDPI (
window.devicePixelRatiobằng 2 hoặc 3) làm tròn bố cục dưới-pixel về một lưới vật lý mịn hơn so với màn hình 1x, làm dịch chuyển phần thập phân của mọi tọa độ. Xem tài liệu MDN vềdevicePixelRatiođể biết trình duyệt để lộ thông tin này ra sao. - Tình trạng có sẵn của phông và cơ chế dự phòng. Nếu phông được yêu cầu không được cài, trình duyệt sẽ thay bằng một phông dự phòng có kích thước khác — cùng cơ chế mà lấy dấu vân tay phông chữ dựa vào, chỉ khác là ở đây tín hiệu là hình học hình chữ nhật thô, chứ không phải một bit đơn giản "có mặt/vắng mặt".
- Engine và phiên bản trình duyệt. Chromium (Blink), Firefox (Gecko) và Safari (WebKit) mỗi cái đều có logic dàn trang văn bản và ngắt dòng riêng, nên cùng một đoạn markup có thể hợp lệ khi đo lệch nhau vài phần trăm pixel giữa các engine, và đôi khi giữa các phiên bản của cùng một engine.
- Mức thu phóng và thu phóng văn bản của hệ điều hành. Zoom trang và thu phóng trợ năng cấp hệ điều hành (tính năng "làm chữ to hơn" của Windows, thu phóng màn hình của macOS) đều đi qua cùng pipeline bố cục và làm dịch chuyển phần dư dưới-pixel.
Không cái nào trong số này là tùy chọn mà ai đó cố tình bật lên vì quyền riêng tư. Chúng là tác dụng phụ của việc kết xuất bình thường — đó chính là lý do vì sao các hình chữ nhật kết quả ổn định với một thiết bị, một phiên làm việc nhất định, nhưng lại khác nhau giữa thiết bị này với thiết bị khác.
ClientRects fingerprinting so với canvas fingerprinting
Hai kỹ thuật này là "họ hàng" gần nhau — cả hai đều khai thác khác biệt trong pipeline kết xuất bắt nguồn từ phông chữ, GPU và engine văn bản của hệ điều hành — nhưng chúng khác nhau ở chỗ đụng vào gì và dễ bị phát hiện đến mức nào.
| Thuộc tính | ClientRects fingerprinting | Canvas fingerprinting |
|---|---|---|
| Bề mặt API | Bố cục DOM thông thường (getClientRects, getBoundingClientRect) | <canvas> + ngữ cảnh 2D (toDataURL, getImageData) |
| Cần đọc pixel | Không | Có |
| Bị các trình chặn canvas chuyên biệt nhìn thấy | Không | Có — tiện ích mở rộng móc trực tiếp vào các lệnh gọi này |
| Nguồn tín hiệu | Hình học bố cục văn bản/phần tử ở mức dưới-pixel | Màu pixel đã raster hóa |
| Entropy điển hình | Trung bình khi đứng riêng; mạnh khi kết hợp với phông chữ | Cao khi đứng riêng |
| Có thể bị phát hiện là "đã đọc một canvas ẩn" | Không áp dụng — không liên quan đến canvas | Có, qua việc giám sát lệnh gọi API |
Hệ quả thực tiễn chính là điều khiến rect fingerprinting hấp dẫn với cả bên theo dõi lẫn nhà cung cấp trình duyệt anti-detect: bất kỳ biện pháp phòng vệ nào chuyên theo dõi lệnh gọi API canvas — tiện ích chặn canvas, lớp farbling, hay script giám sát kiểu như trong bài hướng dẫn canvas của chúng tôi — đều không có gì để chặn ở đây, bởi không có canvas nào được tạo ra cả. Một script chỉ cần lặng lẽ đo bố cục của văn bản và tiêu đề thông thường vốn đã có sẵn trên trang, để tạo ra một tín hiệu tương đương.
Việc đo lường thực sự diễn ra thế nào
Một cách triển khai điển hình sẽ kết xuất vài phần tử văn bản có style — thường trộn nhiều phông, cỡ chữ, và các thuộc tính CSS như letter-spacing vốn được biết là gây ra làm tròn dưới-pixel khác nhau — rồi đọc lại hình chữ nhật của chúng:
// Phác thảo minh họa cho việc đo dựa trên rects
function measureRects() {
const probe = document.createElement('div');
probe.style.cssText = 'position:absolute; visibility:hidden; font-size:14px; letter-spacing:0.3px;';
probe.style.fontFamily = 'Arial, sans-serif';
probe.textContent = 'BrowserInsight fingerprint probe 0123456789';
document.body.appendChild(probe);
const rects = probe.getClientRects();
const values = Array.from(rects).flatMap(r => [r.width, r.height, r.left, r.top]);
document.body.removeChild(probe);
return values; // được đưa vào hàm băm cùng các tín hiệu khác
}
Phần tử này không cần phải hiển thị — visibility: hidden vẫn tham gia vào bố cục như bình thường, nên hình chữ nhật nó tạo ra là thật. Nhiều chuỗi thử, phông chữ và tổ hợp CSS thường được đo và băm cùng nhau, cùng cách tiếp cận "đo nhiều tín hiệu nhỏ, rồi kết hợp lại" được dùng phổ biến trong các kỹ thuật lấy dấu vân tay nói chung — xem hướng dẫn lấy dấu vân tay trình duyệt của chúng tôi để biết các tín hiệu như vậy chồng lên nhau thành một định danh tổng thể ra sao.
Kỹ thuật này xuất hiện ở đâu trong thực tế
Kỹ thuật này không nhận được nhiều sự chú ý từ báo chí như canvas hay WebGL, nhưng nó là một điều đã được biết đến ở hai góc cụ thể của hệ sinh thái:
- Các nhà cung cấp giải pháp lấy dấu vân tay/chống gian lận đưa các phép đo dựa trên rects vào như một trong nhiều tín hiệu đầu vào, chính vì nó rẻ để tính toán và trực giao với các biện pháp phòng vệ mà hầu hết công cụ bảo mật quyền riêng tư tập trung vào.
- Các trình duyệt anti-detect — công cụ được xây dựng để mỗi thực thể trình duyệt trình diện một hồ sơ dấu vân tay khác nhau nhưng nhất quán — coi trọng kỹ thuật này đến mức cung cấp hẳn các tùy chọn điều khiển riêng. Cả GoLogin lẫn Dolphin{anty} đều có cài đặt chuyên dụng để giả mạo hoặc chuẩn hóa đầu ra "Rects", nằm cạnh các công tắc canvas và WebGL của chúng. Việc tồn tại một công tắc được xây dựng riêng là một chỉ dấu hợp lý cho thấy "tín hiệu này thực sự bị kiểm tra" — các nhà cung cấp không xây dựng công cụ giả mạo cho những tín hiệu không ai đọc.
Cách giảm mức độ bị lộ
Không có công tắc "tắt getClientRects" chuyên dụng nào trong các trình duyệt phổ biến, bởi API này thiết yếu cho bố cục thông thường — chọn văn bản, cuộn đến phần tử, tooltip, và gần như mọi framework giao diện JavaScript đều phụ thuộc vào nó. Các biện pháp giảm thiểu khả dụng phản ánh những gì hiệu quả chống lại canvas fingerprinting, vì cả hai có chung gốc rễ:
- Ưu tiên sự đồng nhất hơn là tùy biến. Tor Browser chuẩn hóa cách kết xuất phông chữ và giảm độ chính xác của một số API bố cục chi tiết hơn, thu hẹp nhóm người mà bạn có thể bị phân biệt trong đó — cùng triết lý mà nó áp dụng cho canvas.
- Hạn chế phông chữ và tiện ích mở rộng đã cài. Mỗi phông chữ thêm vào là thêm một cách để cơ chế thay thế dự phòng làm dịch chuyển kích thước hình chữ nhật. Một bộ phông mặc định trên một hệ điều hành cài đặt gốc khó bị nhận diện riêng hơn nhiều so với một hệ thống đã được tùy biến nặng.
- Dùng các biện pháp bảo vệ kiểu resistFingerprinting.
privacy.resistFingerprintingcủa Firefox làm tròn và chuẩn hóa một số giá trị liên quan đến kết xuất, giảm phương sai dưới-pixel mà kỹ thuật này phụ thuộc vào — theo cách tương tự nó giới hạn đầu ra canvas và WebGL. - Kiểm tra xem bạn đang để lộ những gì. Chạy công cụ kiểm tra dấu vân tay của BrowserInsight để xem tín hiệu canvas, WebGL và các tín hiệu kết xuất khác của bạn ở một nơi, rồi so sánh kết quả giữa trình duyệt thông thường và một trình duyệt đã tăng cường quyền riêng tư để biết cài đặt nào thực sự tạo ra khác biệt.
Cũng như canvas, nghịch lý chống-lấy-dấu-vân-tay áp dụng ở đây: một bản giả mạo rects tự chế, hiếm gặp mà làm quá tay — trả về những con số tròn đáng ngờ, hoặc cho phương sai dưới-pixel bằng 0 ở mọi phép thử — có thể lại nổi bật hơn chính tín hiệu gốc mà nó định che giấu.
Câu hỏi thường gặp
ClientRects fingerprinting có giống canvas fingerprinting không?
Không, dù chúng có liên hệ chặt chẽ với nhau. Canvas fingerprinting đọc lại pixel đã raster hóa từ một <canvas> ẩn; ClientRects fingerprinting đọc hình học bố cục dưới-pixel của các phần tử DOM hoặc văn bản thông thường, hoàn toàn không dùng đến canvas. Cả hai đều bắt nguồn từ khác biệt trong kết xuất phông chữ và dàn trang văn bản của nền tảng, nên chúng thường có tương quan với nhau, nhưng một biện pháp phòng vệ chỉ xây dựng cho canvas thì không làm gì được để chặn kỹ thuật này.
Tiện ích chặn canvas có ngăn được kỹ thuật này không?
Tự nó thì không. Trình chặn canvas móc vào các API chuyên biệt cho canvas như toDataURL() và getImageData(). getClientRects() và getBoundingClientRect() là các phương thức bố cục DOM không liên quan, nên một trình chặn chỉ nhắm vào canvas không có lý do gì để can thiệp vào chúng.
Kỹ thuật này có thể tự nó định danh được tôi không?
Hiếm khi đạt độ tin cậy cao khi đứng một mình — nhiều thiết bị có pipeline kết xuất tương tự nhau và cho ra hình chữ nhật tương đương. Nó hữu ích nhất với bên theo dõi khi kết hợp với phông chữ, canvas, WebGL và các thuộc tính thụ động khác, giống như cách mỗi tín hiệu riêng lẻ trong một dấu vân tay đầy đủ chỉ đóng góp một phần entropy chứ không phải toàn bộ danh tính.
Vì sao các trình duyệt anti-detect lại nhắc riêng đến cài đặt "Rects"?
Bởi kỹ thuật này có thật và bị một số nhà cung cấp giải pháp lấy dấu vân tay và chống gian lận thực sự kiểm tra. Các công cụ được xây dựng để trình diện một danh tính giả mạo nhất quán buộc phải chuẩn hóa hoặc ngẫu nhiên hóa nó, giống hệt như chúng làm với canvas và WebGL — nếu không, tín hiệu rects sẽ làm lộ thiết bị thật đằng sau một hồ sơ nếu không thì đã được giả mạo khá tốt.
Kết luận
ClientRects fingerprinting là lời nhắc rằng "phòng vệ chống lấy dấu vân tay" không thể chỉ có nghĩa là "chặn canvas rồi coi như xong". Bất kỳ API nào đủ chính xác để phản ánh cách kết xuất phông chữ, tỷ lệ DPI, hay dàn trang văn bản của nền tảng, đều đủ chính xác để lấy dấu vân tay — và các phương thức bố cục DOM thông thường mà mọi ứng dụng web đã sẵn phụ thuộc vào đáp ứng đúng điều đó. Hiểu cơ chế này là điều giúp bạn đánh giá xem một công cụ bảo vệ quyền riêng tư nào đó có thực sự bao phủ nó hay không, thay vì mặc định rằng bảo vệ canvas đã là toàn bộ câu chuyện.
Đọc thêm:


