前書き
ブラウザだけを使用してマシンを一意に識別する方法があるかどうか、またはこれからもそうなるかはわかりません。主な理由は次のとおりです。
- ユーザーのコンピューターにデータを保存する必要があります。このデータは、ユーザーがいつでも削除できます。あなたが立ち往生しているマシンごとに一意であるこのデータを再作成する方法がない限り。
- 検証。なりすまし、セッションの乗っ取りなどを防ぐ必要があります。
Cookieを使用せずにコンピューターを追跡する方法がある場合でも、それをバイパスする方法と、これを自動的に実行するソフトウェアは常に存在します。コンピューターに基づいて何かを本当に追跡する必要がある場合は、ネイティブアプリケーション(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つの異なるセッションが発生します。これが問題の場合は、ここで読むのをやめることができます。
- ユーザーがログインしていない場合、セッションは期限切れになります。ユーザーがログインしていない場合、ユーザーはゲストセッションを使用します。ゲストセッションは、ユーザーがCookieとブラウザキャッシュを削除すると無効になります。
実装
これを実装する方法はたくさんあります。私はそれらをカバーすることができないと思います私がこれを意見の多い答えにする私のお気に入りをリストします。それを覚えておいてください。
基本
永久クッキーと呼ばれるものを使用してセッションを追跡します。これは、ユーザーがCookieを削除したり、ブラウザを更新したりしても、自動的に再作成されるデータです。ただし、ユーザーがCookieとブラウジングキャッシュの両方を削除しても、それは存続しません。
これを実装するには、ブラウザーのキャッシュメカニズム(RFC)、WebStorage API(MDN)、およびブラウザーのCookie(RFC、Google Analytics)を使用します。
法的
追跡IDを利用するためには、好ましくは、サブ見出しの下に、あなたのプライバシーポリシーと利用のあなたの条件の両方に追加する必要があります追跡。我々は両方の上の次のキーを使用しますdocument.cookie
と window.localStorage
:
- _ga:Google Analyticsデータ
- __utma:Google AnalyticsトラッキングCookie
- sid:SessionID
プライバシーポリシーへのリンクと、トラッキングを使用するすべてのページに利用規約を必ず含めてください。
セッションデータはどこに保存しますか?
セッションデータは、Webサイトデータベースまたはユーザーのコンピューターに保存できます。私は通常、サードパーティのアプリケーション(Google Analytics / Clickyなど)を使用する小規模なサイト(連続接続が1万を超えない)で作業しているので、クライアントコンピューターにデータを保存するのが最善です。これには次の利点があります。
- データベース検索/オーバーヘッド/負荷/待ち時間/スペースなどはありません。
- ユーザーは、迷惑メールを書く必要なく、いつでも自分のデータを削除できます。
と欠点:
- データは暗号化/復号化および署名/検証される必要があり、クライアント(それほど悪くない)およびサーバー(bah!)でCPUオーバーヘッドが発生します。
- ユーザーがCookieとキャッシュを削除すると、データが削除されます。(これは私が本当に欲しいものです)
- ユーザーがオフラインになると、データを分析に使用できなくなります。(現在閲覧しているユーザーのみの分析)
UUIDS
- BrowserID:ブラウザのユーザーエージェント文字列から生成された一意のID。
Browser|BrowserVersion|OS|OSVersion|Processor|MozzilaMajorVersion|GeckoMajorVersion
- ComputerID:ユーザーのIPアドレスとHTTPSセッションキーから生成されます。
getISP(requestIP)|getHTTPSClientKey()
- FingerPrintID:変更されたfinger.jsに基づくJavaScriptベースのフィンガープリント。
FingerPrint.get()
- SessionID:ユーザーが最初にサイトにアクセスしたときに生成されたランダムキー。
BrowserID|ComputerID|randombytes(256)
- GoogleID:
__utma
Cookie から生成されます。getCookie(__utma).uniqueid
機構
先日、彼女と一緒にウェンディウィリアムズのショーを見ていたとき、ホストが視聴者に少なくとも月に1回はブラウザの履歴を削除するように勧めたとき、完全に恐怖になりました。ブラウザの履歴を削除すると、通常、次のような影響があります。
- 訪問したウェブサイトの履歴を削除します。
- cookieと
window.localStorage
(aww man)を削除します。
最新のブラウザのほとんどは、このオプションをすぐに利用できますが、友達を恐れません。解決策があるからです。ブラウザには、スクリプトや画像などを保存するためのキャッシュメカニズムがあります。通常、履歴を削除しても、このブラウザキャッシュは残ります。ここにデータを保存する方法が必要です。これを行うには2つの方法があります。より良い方法は、SVG画像を使用して、データをタグ内に格納することです。この方法では、Flashを使用して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を固定するにはどうすればよいですか?
Cache-Control、Last-Modified、およびETag HTTPヘッダーを使用してこれを実現できます。SessionID
etagヘッダーの値としてas を使用できます。
setHeaders({
"ETag": SessionID,
"Last-Modified": new Date(0).toUTCString(),
"Cache-Control": "private, max-age=31536000, s-max-age=31536000, must-revalidate"
})
Last-Modified
ヘッダーは、このファイルが基本的に変更されないことをブラウザに伝えます。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
は最初のバージョンを実行するように応答を受け取りtracking.js
ます。削除されtracking.js
たSessionID
を実行して復元します。
検証
Haxor Xがまだログインしている間に顧客のCookieを盗んだとしましょう。どのようにして保護しますか?暗号化とブラウザのフィンガープリントで救出。の元の定義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;
ハクソールの攻撃が機能するためには、次のことが必要です。
- 同じ
ComputerID
です。つまり、被害者(Tricky)と同じISPプロバイダーが必要です。これにより、被害者は自国で訴訟を起こす機会が与えられます。Haxorはまた、被害者(ハード)からHTTPSセッションキーを取得する必要があります。
- 同じ
BrowserID
です。誰でもユーザーエージェント文字列を偽装できます(迷惑)。
- 自分の偽物
SessionID
(非常に難しい)を作成できる。タイムスタンプを使用して暗号化/署名鍵を生成するため、ボリューム攻撃は機能しません。基本的には、セッションごとに新しい鍵を生成するようなものです。その上、ランダムなバイトを暗号化するため、単純な辞書攻撃も問題外です。
転送GoogleID
およびFingerprintID
(ajaxまたは非表示フィールドを介して)検証を改善し、それらと照合できます。
if( GoogleID != getStoredGoodleID($sid) ) return false;
if( byte_difference(FingerPrintID, getStoredFingerprint($sid) > 10%) return false;