บทนำ
ฉันไม่รู้ว่าจะมีวิธีระบุเครื่องโดยใช้เบราว์เซอร์เพียงอย่างเดียวหรือไม่ เหตุผลหลักคือ:
- คุณจะต้องบันทึกข้อมูลในคอมพิวเตอร์ของผู้ใช้ ผู้ใช้สามารถลบข้อมูลนี้ได้ตลอดเวลา ถ้าคุณไม่มีวิธีในการสร้างข้อมูลนี้ซึ่งไม่ซ้ำกันสำหรับแต่ละเครื่องทุกเครื่องแล้วติดของคุณ
- การตรวจสอบ คุณจำเป็นต้องป้องกันการปลอมแปลงการเซสชั่นการจี้ ฯลฯ
แม้ว่าจะมีวิธีการติดตามคอมพิวเตอร์โดยไม่ใช้คุกกี้ แต่ก็มีวิธีเลี่ยงผ่านและซอฟต์แวร์ที่จะทำสิ่งนี้โดยอัตโนมัติ หากคุณต้องการติดตามสิ่งที่อยู่บนคอมพิวเตอร์คุณจะต้องเขียนแอปพลิเคชันเนทีฟ (Apple Store / Android Store / Windows Program / ฯลฯ )
ฉันอาจไม่สามารถให้คำตอบสำหรับคำถามที่คุณถาม แต่ฉันสามารถแสดงวิธีใช้การติดตามเซสชัน ด้วยการติดตามเซสชันคุณพยายามติดตามเซสชันการสืบค้นแทนคอมพิวเตอร์ที่เข้าชมเว็บไซต์ของคุณ ด้วยการติดตามเซสชันสกีมาฐานข้อมูลของคุณจะมีลักษณะดังนี้:
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
}, ...]
ข้อดีของการติดตามแบบเซสชัน:
- สำหรับผู้ใช้เข้าสู่ระบบคุณก็สามารถสร้างเซสชัน id เดียวกันจากผู้ใช้
username
/ /password
email
sessionID
คุณยังสามารถติดตามผู้ใช้ของผู้เข้าพักใช้
- แม้ว่าหลายคนใช้คอมพิวเตอร์เครื่องเดียวกัน (เช่นไซเบอร์คาเฟ่) คุณสามารถติดตามพวกเขาแยกกันได้หากพวกเขาลงชื่อเข้าใช้
ข้อเสียของการติดตามเซสชัน:
- เซสชันใช้เบราว์เซอร์ไม่ใช่คอมพิวเตอร์ หากผู้ใช้ใช้ 2 เบราว์เซอร์ที่แตกต่างกันก็จะส่งผลใน 2 ช่วง หากนี่เป็นปัญหาคุณสามารถหยุดอ่านได้ที่นี่
- เซสชั่นหมดอายุหากผู้ใช้ไม่ได้เข้าสู่ระบบหากผู้ใช้ไม่ได้เข้าสู่ระบบพวกเขาจะใช้เซสชั่นผู้เยี่ยมชมซึ่งจะถูกยกเลิกหากผู้ใช้ลบคุกกี้และแคชเบราว์เซอร์
การดำเนินงาน
การดำเนินการนี้มีหลายวิธี ฉันไม่คิดว่าฉันสามารถครอบคลุมพวกเขาทั้งหมดที่ฉันเพิ่งจะแสดงรายการที่ชื่นชอบซึ่งจะทำให้นี้คำตอบความเห็น จำไว้ในใจ
ข้อมูลพื้นฐานเกี่ยวกับ
ฉันจะติดตามเซสชันโดยใช้สิ่งที่เรียกว่าคุกกี้ถาวร นี่คือข้อมูลที่จะสร้างตัวเองใหม่โดยอัตโนมัติแม้ว่าผู้ใช้จะลบคุกกี้หรืออัปเดตเบราว์เซอร์ของเขา อย่างไรก็ตามผู้ใช้จะไม่สามารถลบทั้งคุกกี้และแคชการค้นหาได้
ในการดำเนินการนี้ฉันจะใช้กลไกการแคชของเบราว์เซอร์ ( RFC ), WebStorage API ( MDN ) และคุกกี้ของเบราว์เซอร์ ( RFC , Google Analytics )
ถูกกฎหมาย
เพื่อที่จะใช้ประโยชน์จากการติดตามรหัสที่คุณจำเป็นต้องเพิ่มให้ทั้งนโยบายความเป็นส่วนตัวของคุณและเงื่อนไขของคุณในการใช้โดยเฉพาะอย่างยิ่งภายใต้การย่อยหัวข้อการติดตาม เราจะใช้ปุ่มต่อไปนี้ทั้งบนdocument.cookie
และ window.localStorage
:
- _ga : ข้อมูล Google Analytics
- __utma : คุกกี้ติดตามของ Google Analytics
- sid : SessionID
ตรวจสอบให้แน่ใจว่าคุณมีลิงก์ไปยังนโยบายความเป็นส่วนตัวและข้อกำหนดการใช้งานของทุกหน้าที่ใช้การติดตาม
ฉันจะเก็บข้อมูลเซสชันของฉันได้ที่ไหน
คุณสามารถจัดเก็บข้อมูลเซสชันของคุณในฐานข้อมูลเว็บไซต์ของคุณหรือในคอมพิวเตอร์ของผู้ใช้ เนื่องจากปกติฉันทำงานบนไซต์ที่เล็กกว่า (ให้มากกว่า 10,000 การเชื่อมต่อต่อเนื่อง) ที่ใช้แอปพลิเคชันบุคคลที่สาม (Google Analytics / Clicky / ฯลฯ ) จึงเป็นการดีที่สุดที่ฉันจะเก็บข้อมูลไว้ในคอมพิวเตอร์ของลูกค้า นี่มีข้อดีดังต่อไปนี้:
- ไม่มีการค้นหา / โอเวอร์เฮด / โหลด / เวลาแฝง / พื้นที่ / ฐานข้อมูล
- ผู้ใช้สามารถลบข้อมูลได้ทุกเมื่อที่ต้องการโดยไม่จำเป็นต้องเขียนอีเมลที่น่ารำคาญ
และข้อเสีย:
- ข้อมูลจะต้องมีการเข้ารหัส / ถอดรหัสและลงนาม / ตรวจสอบซึ่งจะสร้างค่าใช้จ่ายซีพียูบนไคลเอนต์ (ไม่เลวร้าย) และเซิร์ฟเวอร์ (บาห์!)
- ข้อมูลจะถูกลบเมื่อผู้ใช้ลบคุกกี้และแคช (นี่คือสิ่งที่ฉันต้องการจริงๆ)
- ข้อมูลไม่พร้อมใช้งานสำหรับการวิเคราะห์เมื่อผู้ใช้ออฟไลน์ (การวิเคราะห์สำหรับผู้ใช้ที่กำลังเรียกดูในปัจจุบันเท่านั้น)
UUIDs
- BrowserID : รหัสเฉพาะที่สร้างจากสตริงตัวแทนผู้ใช้เบราว์เซอร์
Browser|BrowserVersion|OS|OSVersion|Processor|MozzilaMajorVersion|GeckoMajorVersion
- ComputerID : สร้างจากที่อยู่ IP ของผู้ใช้และรหัสเซสชัน HTTPS
getISP(requestIP)|getHTTPSClientKey()
- FingerPrintID : JavaScript พิมพ์ลายนิ้วมือตามขึ้นอยู่กับการปรับเปลี่ยนfingerprint.js
FingerPrint.get()
- SessionID : สร้างรหัสสุ่มเมื่อผู้ใช้เยี่ยมชมไซต์ครั้งที่ 1
BrowserID|ComputerID|randombytes(256)
- GoogleID : สร้างจาก
__utma
คุกกี้getCookie(__utma).uniqueid
กลไก
เมื่อวันก่อนฉันกำลังดูวิลเลียมส์วิลเลียมส์แสดงกับแฟนสาวของฉันและรู้สึกตกใจอย่างยิ่งเมื่อโฮสต์แนะนำให้ผู้ชมของเธอลบประวัติเบราว์เซอร์อย่างน้อยเดือนละครั้ง การลบประวัติเบราว์เซอร์ตามปกติจะมีผลต่อไปนี้:
- ลบประวัติเว็บไซต์ที่เข้าชม
- ลบคุกกี้และ
window.localStorage
(aww man)
เบราว์เซอร์ที่ทันสมัยส่วนใหญ่ทำให้ตัวเลือกนี้พร้อมใช้งาน แต่ไม่กลัวเพื่อน สำหรับมีทางออก เบราว์เซอร์มีกลไกการแคชเพื่อจัดเก็บสคริปต์ / ภาพและอื่น ๆ โดยทั่วไปแม้ว่าเราจะลบประวัติของเราแคชเบราว์เซอร์นี้ยังคงอยู่ สิ่งที่เราต้องการคือวิธีเก็บข้อมูลของเราที่นี่ มี 2 วิธีในการทำเช่นนี้ สิ่งที่ดีกว่าคือการใช้ภาพ SVG และเก็บข้อมูลของเราไว้ในแท็ก วิธีนี้ยังสามารถดึงข้อมูลได้แม้ว่าจะปิดการใช้งาน JavaScript โดยใช้แฟลช อย่างไรก็ตามเนื่องจากมันค่อนข้างซับซ้อนฉันจะแสดงให้เห็นถึงวิธีการอื่นที่ใช้ JSONP ( Wikipedia )
example.com/assets/js/tracking.js (จริง ๆ แล้ว tracking.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);
}
ตอนนี้เราสามารถรับกุญแจเซสชันได้ตลอดเวลา:
window.__sid || window.localStorage.getItem("sid") || getCookie("sid") || ""
ฉันจะติดตั้ง tracking.js ในเบราว์เซอร์ได้อย่างไร
เราสามารถทำได้โดยใช้ส่วนควบคุมแคช , Last-ModifiedและETag HTTP header เราสามารถใช้SessionID
เป็นค่าสำหรับส่วนหัว etag:
setHeaders({
"ETag": SessionID,
"Last-Modified": new Date(0).toUTCString(),
"Cache-Control": "private, max-age=31536000, s-max-age=31536000, must-revalidate"
})
Last-Modified
header บอกเบราว์เซอร์ว่าไฟล์นี้ไม่มีการแก้ไข Cache-Control
บอกผู้รับมอบฉันทะและเกตเวย์ไม่ให้แคชเอกสาร แต่บอกให้เบราว์เซอร์ทำการแคชเป็นเวลา 1 ปี
ครั้งต่อไปที่เบราว์เซอร์ร้องขอเอกสารจะส่งIf-Modified-Since
และIf-None-Match
ส่วนหัว เราสามารถใช้สิ่งเหล่านี้เพื่อ304 Not Modified
ตอบกลับ
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();
}
ตอนนี้ทุกครั้งที่เบราว์เซอร์ร้องขอtracking.js
เซิร์ฟเวอร์ของเราจะตอบสนองกับผลและบังคับให้มีการดำเนินการของสำเนาของ304 Not Modified
tracking.js
ฉันยังไม่เข้าใจ อธิบายให้ฉัน
สมมติว่าผู้ใช้ล้างประวัติการเข้าชมและรีเฟรชหน้าเว็บ สิ่งเดียวที่เหลืออยู่ในคอมพิวเตอร์ของผู้ใช้คือสำเนาของtracking.js
แคชเบราว์เซอร์ เมื่อเบราว์เซอร์ร้องขอtracking.js
มันจะได้รับการ304 Not Modified
ตอบกลับซึ่งทำให้มันเรียกใช้เวอร์ชันที่ 1 ของtracking.js
มัน tracking.js
ดำเนินการและคืนค่าSessionID
ที่ถูกลบ
การตรวจสอบ
สมมติว่า Haxor X ขโมยคุกกี้ลูกค้าของเราในขณะที่พวกเขายังคงเข้าสู่ระบบเราจะปกป้องพวกเขาได้อย่างไร? การเข้ารหัสและลายนิ้วมือเบราว์เซอร์เพื่อช่วยเหลือ โปรดจำไว้ว่าคำนิยามดั้งเดิมของเราSessionID
คือ:
BrowserID|ComputerID|randomBytes(256)
เราสามารถเปลี่ยนสิ่งนี้เป็น:
Timestamp|BrowserID|ComputerID|encrypt(randomBytes(256), hk)|sign(Timestamp|BrowserID|ComputerID|randomBytes(256), hk)
hk = sign(Timestamp|BrowserID|ComputerID, serverKey)
ที่ไหน
ตอนนี้เราสามารถตรวจสอบความถูกต้องของเราSessionID
โดยใช้อัลกอริทึมต่อไปนี้:
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;
ตอนนี้เพื่อให้การโจมตีของ Haxor ต้องทำงาน:
ComputerID
มีเหมือนกัน นั่นหมายความว่าพวกเขาจะต้องมีผู้ให้บริการ ISP รายเดียวกันกับเหยื่อ (Tricky) นี่จะเป็นการเปิดโอกาสให้เหยื่อของเราดำเนินการทางกฎหมายในประเทศของตนเอง Haxor จะต้องได้รับกุญแจเซสชั่น HTTPS จากเหยื่อ (ยาก)
BrowserID
มีเหมือนกัน ทุกคนสามารถหลอกสตริงตัวแทนผู้ใช้ (น่ารำคาญ)
- สามารถสร้างปลอมของตัวเอง
SessionID
(ยากมาก) ปริมาณ atacks จะไม่ทำงานเพราะเราใช้การประทับเวลาเพื่อสร้างคีย์การเข้ารหัส / เซ็นชื่อดังนั้นโดยพื้นฐานแล้วมันเหมือนกับการสร้างคีย์ใหม่สำหรับแต่ละเซสชั่น ยิ่งไปกว่านั้นเราเข้ารหัสแบบสุ่มไบต์เพื่อให้การโจมตีพจนานุกรมง่าย ๆ ก็ออกจากคำถาม
เราสามารถปรับปรุงการตรวจสอบโดยการส่งต่อGoogleID
และFingerprintID
(ผ่าน ajax หรือเขตข้อมูลที่ซ่อนอยู่) และการจับคู่กับสิ่งเหล่านั้น
if( GoogleID != getStoredGoodleID($sid) ) return false;
if( byte_difference(FingerPrintID, getStoredFingerprint($sid) > 10%) return false;