Giới thiệu
Tôi không biết nếu có hoặc sẽ có một cách để nhận dạng duy nhất các máy chỉ sử dụng trình duyệt. Những lý do chính là:
- Bạn sẽ cần lưu dữ liệu trên máy tính của người dùng. Dữ liệu này có thể bị xóa bởi người dùng bất cứ lúc nào. Trừ khi bạn có cách để tạo lại dữ liệu này là duy nhất cho mỗi máy và sau đó máy của bạn bị kẹt.
- Thẩm định. Bạn cần bảo vệ chống giả mạo, chiếm quyền điều khiển phiên, v.v.
Ngay cả khi có những cách để theo dõi máy tính mà không sử dụng cookie, sẽ luôn có cách để vượt qua nó và phần mềm sẽ tự động làm việc này. Nếu bạn thực sự cần theo dõi một cái gì đó dựa trên máy tính, bạn sẽ phải viết một ứng dụng gốc (Apple Store / Android Store / Chương trình Windows / vv).
Tôi có thể không thể đưa ra câu trả lời cho câu hỏi bạn đã hỏi nhưng tôi có thể chỉ cho bạn cách triển khai theo dõi phiên. Với theo dõi phiên, bạn cố gắng theo dõi phiên duyệt thay vì máy tính truy cập trang web của bạn. Bằng cách theo dõi phiên, lược đồ cơ sở dữ liệu của bạn sẽ trông như thế này:
sesssion:
sessionID: string
// Global session data goes here
computers: [{
BrowserID: string
ComputerID: string
FingerprintID: string
userID: string
authToken: string
ipAddresses: ["203.525....", "203.525...", ...]
// Computer session data goes here
}, ...]
Ưu điểm của theo dõi dựa trên phiên:
- Đối với người dùng đã đăng nhập, bạn luôn có thể tạo cùng một id phiên từ người dùng
username
/ password
/ email
.
- Bạn vẫn có thể theo dõi người dùng khách bằng cách sử dụng
sessionID
.
- Ngay cả khi một số người sử dụng cùng một máy tính (ví dụ như cybercafe), bạn có thể theo dõi họ riêng nếu họ đăng nhập.
Nhược điểm của theo dõi dựa trên phiên:
- Phiên là dựa trên trình duyệt và không dựa trên máy tính. Nếu người dùng sử dụng 2 trình duyệt khác nhau, nó sẽ dẫn đến 2 phiên khác nhau. Nếu đây là một vấn đề bạn có thể dừng đọc ở đây.
- Phiên hết hạn nếu người dùng chưa đăng nhập. Nếu người dùng chưa đăng nhập, họ sẽ sử dụng phiên khách sẽ bị vô hiệu nếu người dùng xóa cookie và bộ đệm của trình duyệt.
Thực hiện
Có nhiều cách để thực hiện điều này. Tôi không nghĩ rằng tôi có thể bao quát tất cả chúng tôi sẽ chỉ liệt kê yêu thích của tôi mà sẽ làm cho câu trả lời này có ý kiến . Hãy ghi nhớ điều đó.
Khái niệm cơ bản
Tôi sẽ theo dõi phiên bằng cách sử dụng cái được gọi là cookie mãi mãi. Đây là dữ liệu sẽ tự động tạo lại ngay cả khi người dùng xóa cookie hoặc cập nhật trình duyệt của mình. Tuy nhiên, nó sẽ không tồn tại khi người dùng xóa cả cookie và bộ nhớ cache duyệt web của họ.
Để thực hiện điều này, tôi sẽ sử dụng cơ chế lưu trữ của trình duyệt ( RFC ), API WebStorage ( MDN ) và cookie trình duyệt ( RFC , Google Analytics ).
Hợp pháp
Để sử dụng id theo dõi, bạn cần thêm chúng vào cả chính sách bảo mật và điều khoản sử dụng của bạn tốt nhất là theo dõi Tiêu đề phụ . Chúng tôi sẽ sử dụng các phím sau trên cả hai document.cookie
và window.localStorage
:
- _ga : dữ liệu Google Analytics
- __utma : cookie theo dõi Google Analytics
- sid : sessionID
Đảm bảo bạn bao gồm các liên kết đến chính sách quyền riêng tư và điều khoản sử dụng của bạn trên tất cả các trang sử dụng theo dõi.
Tôi lưu trữ dữ liệu phiên của mình ở đâu?
Bạn có thể lưu trữ dữ liệu phiên của bạn trong cơ sở dữ liệu trang web của bạn hoặc trên máy tính của người dùng. Vì tôi thường làm việc trên các trang web nhỏ hơn (cho phép hơn 10 nghìn kết nối liên tục) sử dụng các ứng dụng của bên thứ 3 (Google Analytics / Clicky / etc) nên tốt nhất cho tôi để lưu trữ dữ liệu trên máy khách. Điều này có những ưu điểm sau:
- Không có tra cứu cơ sở dữ liệu / phí / tải / độ trễ / không gian / vv
- Người dùng có thể xóa dữ liệu của họ bất cứ khi nào họ muốn mà không cần phải viết cho tôi những email khó chịu.
và nhược điểm:
- Dữ liệu phải được mã hóa / giải mã và ký / xác minh để tạo ra chi phí cpu trên máy khách (không quá tệ) và máy chủ (bah!).
- Dữ liệu sẽ bị xóa khi người dùng xóa cookie và bộ nhớ cache của họ. (đây là những gì tôi muốn thực sự)
- Dữ liệu không có sẵn để phân tích khi người dùng ngoại tuyến. (phân tích chỉ dành cho người dùng đang duyệt)
UUIDS
- BrowserID : Id duy nhất được tạo từ chuỗi tác nhân người dùng trình duyệt.
Browser|BrowserVersion|OS|OSVersion|Processor|MozzilaMajorVersion|GeckoMajorVersion
- ComputerID : Được tạo từ địa chỉ IP của người dùng và khóa phiên HTTPS.
getISP(requestIP)|getHTTPSClientKey()
- FingerPrintID : JavaScript fingerprinting dựa trên cơ sở sửa đổi fingerprint.js .
FingerPrint.get()
- SessionID : Khóa ngẫu nhiên được tạo khi người dùng truy cập trang web đầu tiên.
BrowserID|ComputerID|randombytes(256)
- GoogleID : Được tạo từ
__utma
cookie.getCookie(__utma).uniqueid
Cơ chế
Hôm nọ tôi đang xem chương trình wiamy williams với bạn gái của tôi và hoàn toàn kinh hoàng khi người dẫn chương trình khuyên người xem của cô ấy nên xóa lịch sử trình duyệt của họ ít nhất một lần mỗi tháng. Xóa lịch sử trình duyệt thường có các tác dụng sau:
- Xóa lịch sử của các trang web truy cập.
- Xóa cookie và
window.localStorage
(aww man).
Hầu hết các trình duyệt hiện đại làm cho tùy chọn này có sẵn nhưng không sợ bạn bè. Để có một giải pháp. Trình duyệt có một cơ chế lưu trữ để lưu trữ tập lệnh / hình ảnh và những thứ khác. Thông thường ngay cả khi chúng tôi xóa lịch sử của mình, bộ đệm của trình duyệt này vẫn còn. Tất cả chúng ta cần là một cách để lưu trữ dữ liệu của chúng tôi ở đây. Có 2 phương pháp để làm điều này. Cách tốt hơn là sử dụng hình ảnh SVG và lưu trữ dữ liệu của chúng tôi bên trong các thẻ của nó. Bằng cách này, dữ liệu vẫn có thể được trích xuất ngay cả khi JavaScript bị tắt bằng flash. Tuy nhiên vì điều đó hơi phức tạp nên tôi sẽ trình bày cách tiếp cận khác sử dụng JSONP ( Wikipedia )
example.com/assets/js/tracking.js (thực sự theo dõi.php)
var now = new Date();
var window.__sid = "SessionID"; // Server generated
setCookie("sid", window.__sid, now.setFullYear(now.getFullYear() + 1, now.getMonth(), now.getDate() - 1));
if( "localStorage" in window ) {
window.localStorage.setItem("sid", window.__sid);
}
Bây giờ chúng tôi có thể nhận được khóa phiên của mình bất cứ lúc nào:
window.__sid || window.localStorage.getItem("sid") || getCookie("sid") || ""
Làm cách nào để tôi theo dõi.j.j trong trình duyệt?
Chúng tôi có thể đạt được điều này bằng cách sử dụng các tiêu đề HTTP Cache-Control , Last-Modified và ETag . Chúng ta có thể sử dụng SessionID
giá trị as cho tiêu đề etag:
setHeaders({
"ETag": SessionID,
"Last-Modified": new Date(0).toUTCString(),
"Cache-Control": "private, max-age=31536000, s-max-age=31536000, must-revalidate"
})
Last-Modified
tiêu đề cho trình duyệt biết rằng về cơ bản tệp này không bao giờ được sửa đổi. Cache-Control
nói với proxy và cổng không lưu bộ đệm tài liệu nhưng bảo trình duyệt lưu nó trong 1 năm.
Lần sau trình duyệt yêu cầu tài liệu, nó sẽ gửi If-Modified-Since
và If-None-Match
tiêu đề. Chúng ta có thể sử dụng chúng để trả 304 Not Modified
lời.
example.com/assets/js/tracking.php
$sid = getHeader("If-None-Match") ?: getHeader("if-none-match") ?: getHeader("IF-NONE-MATCH") ?: "";
$ifModifiedSince = hasHeader("If-Modified-Since") ?: hasHeader("if-modified-since") ?: hasHeader("IF-MODIFIED-SINCE");
if( validateSession($sid) ) {
if( sessionExists($sid) ) {
continueSession($sid);
send304();
} else {
startSession($sid);
send304();
}
} else if( $ifModifiedSince ) {
send304();
} else {
startSession();
send200();
}
Bây giờ mỗi khi trình duyệt yêu cầu tracking.js
máy chủ của chúng tôi sẽ phản hồi với 304 Not Modified
kết quả và buộc thực thi bản sao cục bộ tracking.js
.
Tôi vẫn không hiểu. Giải thích cho tôi
Giả sử người dùng xóa lịch sử duyệt web của họ và làm mới trang. Thứ duy nhất còn lại trên máy tính người dùng là một bản sao tracking.js
trong bộ đệm của trình duyệt. Khi trình duyệt yêu cầu, tracking.js
nó nhận được 304 Not Modified
phản hồi khiến nó thực thi phiên bản đầu tiên của tracking.js
nó. tracking.js
thực hiện và khôi phục lại những SessionID
gì đã bị xóa.
Thẩm định
Giả sử Haxor X đánh cắp cookie của khách hàng trong khi họ vẫn đăng nhập. Làm thế nào để chúng tôi bảo vệ họ? Mật mã và dấu vân tay trình duyệt để giải cứu. Hãy nhớ định nghĩa ban đầu của chúng tôi SessionID
là:
BrowserID|ComputerID|randomBytes(256)
Chúng ta có thể thay đổi điều này thành:
Timestamp|BrowserID|ComputerID|encrypt(randomBytes(256), hk)|sign(Timestamp|BrowserID|ComputerID|randomBytes(256), hk)
Ở đâu hk = sign(Timestamp|BrowserID|ComputerID, serverKey)
.
Bây giờ chúng ta có thể xác nhận SessionID
bằng cách sử dụng thuật toán sau:
if( getTimestamp($sid) is older than 1 year ) return false;
if( getBrowserID($sid) !== createBrowserID($_Request, $_Server) ) return false;
if( getComputerID($sid) !== createComputerID($_Request, $_Server) return false;
$hk = sign(getTimestamp($sid) + getBrowserID($sid) + getComputerID($sid), $SERVER["key"]);
if( !verify(getTimestamp($sid) + getBrowserID($sid) + getComputerID($sid) + decrypt(getRandomBytes($sid), hk), getSignature($sid), $hk) ) return false;
return true;
Bây giờ để cuộc tấn công của Haxor hoạt động, họ phải:
- Có cùng
ComputerID
. Điều đó có nghĩa là họ phải có cùng nhà cung cấp ISP là nạn nhân (Tricky). Điều này sẽ cho nạn nhân của chúng tôi cơ hội để thực hiện hành động pháp lý tại đất nước của họ. Haxor cũng phải lấy khóa phiên HTTPS từ nạn nhân (Cứng).
- Có cùng
BrowserID
. Bất cứ ai cũng có thể giả mạo chuỗi User-Agent (Annoying).
- Có thể tạo giả của riêng họ
SessionID
(Rất khó). Khối lượng âm lượng sẽ không hoạt động vì chúng tôi sử dụng dấu thời gian để tạo khóa mã hóa / ký, vì vậy về cơ bản, nó giống như tạo một khóa mới cho mỗi phiên. Trên hết, chúng tôi mã hóa các byte ngẫu nhiên để một cuộc tấn công từ điển đơn giản cũng không còn là vấn đề.
Chúng tôi có thể cải thiện xác thực bằng cách chuyển tiếp GoogleID
và FingerprintID
(thông qua ajax hoặc các trường ẩn) và khớp với các trường đó.
if( GoogleID != getStoredGoodleID($sid) ) return false;
if( byte_difference(FingerPrintID, getStoredFingerprint($sid) > 10%) return false;