Trong nhiều năm, cookie là công cụ chính để nhận diện người dùng trên website. Tuy nhiên, với sự siết chặt của các trình duyệt (ITP, ETP, SameSite, block third-party cookie), cookie ngày càng trở nên kém ổn định và không đáng tin cậy cho các hệ thống analytics, anti-spam hay đo lường traffic thật.
Một giải pháp được cộng đồng sử dụng rộng rãi là FingerprintJS (open-source). Dù thường bị gọi là “bản cơ bản”, nhưng nếu hiểu đúng và thiết kế backend hợp lý, FingerprintJS OSS hoàn toàn đủ dùng cho phần lớn website thực tế.
Bài viết này chia sẻ cách tiếp cận đúng và thiết kế database fingerprint theo hướng thực chiến – nhẹ – dễ scale.
FingerprintJS OSS tạo fingerprint bằng cách thu thập các tín hiệu phía trình duyệt như:
Sau đó, các tín hiệu này được hash để tạo ra một chuỗi định danh gọi là visitorId.
Người ta thường gọi FingerprintJS OSS là “cơ bản” không phải vì nó yếu, mà vì:
Đây là giới hạn thiết kế, không phải nhược điểm kỹ thuật.
👉 Với web tin tức, blog SEO, anti-spam, đo user ẩn danh, những tín hiệu này là quá đủ.
Một sai lầm rất thường gặp:
Coi
visitorId= 1 user vĩnh viễn
Thực tế:
👉 Vì vậy:
Đây chính là lý do cần thiết kế database đúng ngay từ đầu.
Nguyên tắc cốt lõi:
visitors ├── visitor_fingerprints ├── visitor_sessions └── visitor_events (optional)
visitors: đại diện cho người dùng logicvisitor_fingerprints: lưu các fingerprint đã từng thấyvisitor_sessions: hành vi truy cậpvisitor_events: dùng cho anti-spam nâng cao (tuỳ chọn)visitors – user logicCREATE TABLE visitors (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
first_seen DATETIME NOT NULL,
last_seen DATETIME NOT NULL,
total_sessions INT UNSIGNED DEFAULT 0,
total_pages INT UNSIGNED DEFAULT 0,
risk_score TINYINT UNSIGNED DEFAULT 0,
status ENUM('normal','suspicious','blocked') DEFAULT 'normal',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
Bảng này không phụ thuộc fingerprint.
Nó đại diện cho một người dùng logic hoặc một thiết bị ổn định.
visitor_fingerprints – lõi hệ thốngCREATE TABLE visitor_fingerprints (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
visitor_id BIGINT UNSIGNED NOT NULL,
fingerprint_id CHAR(32) NOT NULL,
user_agent_hash CHAR(40) NOT NULL,
ip_prefix VARBINARY(8) NOT NULL,
device_type ENUM('desktop','mobile','tablet','bot','unknown'),
confidence TINYINT UNSIGNED DEFAULT 100,
first_seen DATETIME NOT NULL,
last_seen DATETIME NOT NULL,
seen_count INT UNSIGNED DEFAULT 1,
INDEX idx_fingerprint (fingerprint_id),
INDEX idx_ip_prefix (ip_prefix),
INDEX idx_visitor (visitor_id)
);
Một visitor:
Đây là chìa khoá để hệ thống không bị vỡ dữ liệu theo thời gian.
visitor_sessions – phân biệt user thậtCREATE TABLE visitor_sessions ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, visitor_id BIGINT UNSIGNED NOT NULL, session_key CHAR(40) NOT NULL, ip_address VARBINARY(16) NOT NULL, started_at DATETIME NOT NULL, ended_at DATETIME DEFAULT NULL, page_views INT UNSIGNED DEFAULT 1, duration INT UNSIGNED DEFAULT 0, is_bounce TINYINT(1) DEFAULT 1, INDEX idx_visitor (visitor_id), INDEX idx_session (session_key) );
Bảng này giúp:
visitor_eventsDùng khi cần anti-spam mạnh:
CREATE TABLE visitor_events ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, visitor_id BIGINT UNSIGNED NOT NULL, event_type VARCHAR(32), event_value VARCHAR(255), created_at DATETIME DEFAULT CURRENT_TIMESTAMP );
Ví dụ event:
Khi client gửi dữ liệu lên server:
{
"fingerprint": "abc123",
"user_agent": "...",
"ip": "1.2.3.4"
}
Server xử lý theo thứ tự:
fingerprint_id
👉 Fingerprint đổi không làm mất lịch sử user.
Ví dụ tính điểm rủi ro:
| Điều kiện | Điểm |
|---|---|
| >50 page / 5 phút | +30 |
| >3 fingerprint / 24h | +20 |
| Headless UA | +40 |
| Không canvas | +25 |
Khi vượt ngưỡng:
👉 Với phần lớn website thực tế, mô hình này đạt 80–90% hiệu quả của các giải pháp thương mại, nhưng hoàn toàn miễn phí.
FingerprintJS OSS không hề “yếu”.
Nó chỉ đúng với mục đích thiết kế của nó.
Nếu:
👉 Bạn sẽ có một hệ thống nhận diện user ổn định, bền vững và đủ mạnh cho nhiều năm sử dụng.