序章
ブラウザのみを使用してマシンを一意に識別する方法があるかどうか、またはこれからもそうなるかどうかはわかりません。主な理由は次のとおりです。
- ユーザーのコンピュータにデータを保存する必要があります。このデータは、ユーザーがいつでも削除できます。すべてのマシンに固有のこのデータを再作成する方法がない限り、スタックします。
- 検証。なりすましやセッションハイジャックなどを防ぐ必要があります。
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 を削除したり、ブラウザを更新したりしても、自動的に再作成されるデータです。ただし、ユーザーが Cookie とブラウジング キャッシュの両方を削除した後は存続しません。
これを実装するには、ブラウザーのキャッシュ メカニズム ( RFC )、WebStorage API ( MDN )、およびブラウザーの Cookie ( RFC、Google Analytics ) を使用します。
法的
トラッキング ID を利用するには、プライバシー ポリシーと使用条件の両方に追加する必要があります。document.cookie
と の両方で 次のキーを使用しますwindow.localStorage
。
- _ga : Google アナリティクスのデータ
- __utma : Google アナリティクス トラッキング Cookie
- sid : セッション ID
トラッキングを使用するすべてのページに、プライバシー ポリシーと利用規約へのリンクを必ず含めてください。
セッションデータはどこに保存しますか?
セッション データは、Web サイト データベースまたはユーザーのコンピューターに保存できます。私は通常、サードパーティのアプリケーション (Google Analytics / Clicky / など) を使用する小規模なサイト (連続接続が 10,000 未満) で作業しているため、クライアントのコンピューターにデータを保存するのが最善です。これには次の利点があります。
- データベース ルックアップ / オーバーヘッド / 負荷 / レイテンシ / スペースなどはありません。
- ユーザーは、迷惑なメールを書く必要なく、いつでも自分のデータを削除できます。
と欠点:
- データは暗号化/復号化および署名/検証する必要があり、クライアント (それほど悪くはありません) とサーバー (バー!) で 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
機構
先日、ガールフレンドと一緒にウェンディ・ウィリアムズのショーを見ていて、ホストが視聴者に少なくとも月に一度はブラウザの履歴を削除するようにアドバイスしたとき、完全にぞっとしました. 通常、ブラウザの履歴を削除すると、次のような影響があります。
- 訪問した Web サイトの履歴を削除します。
- Cookie と
window.localStorage
(aww man) を削除します。
最新のブラウザーのほとんどは、このオプションをすぐに利用できるようにしていますが、友達を恐れる必要はありません。解決策があるからです。ブラウザには、スクリプトや画像などを保存するためのキャッシュ メカニズムがあります。通常、履歴を削除しても、このブラウザ キャッシュは残ります。必要なのは、ここにデータを保存する方法だけです。これには 2 つの方法があります。より良い方法は、SVG 画像を使用して、データをそのタグ内に保存することです。これにより、Flash を使用して JavaScript が無効になっている場合でも、データを抽出できます。ただし、それは少し複雑なので、JSONP (ウィキペディア)を使用する別のアプローチを示します。
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;
Haxor の攻撃が機能するためには、次のことを行う必要があります。
- 同じ
ComputerID
です。つまり、被害者 (Tricky) と同じ ISP プロバイダーを使用する必要があります。これにより、被害者は自国で法的措置を講じる機会が得られます。Haxor は、被害者 (ハード) から HTTPS セッション キーも取得する必要があります。
- 同じ
BrowserID
です。誰でも User-Agent 文字列を偽装できます (迷惑)。
- 独自の偽物を作成できる
SessionID
(非常に難しい)。タイムスタンプを使用して暗号化/署名キーを生成するため、ボリューム攻撃は機能しません。基本的には、セッションごとに新しいキーを生成するようなものです。さらに、ランダムなバイトを暗号化するため、単純な辞書攻撃も問題になりません。
GoogleID
(ajax または隠しフィールドを介して) andを転送し、FingerprintID
それらと照合することで、検証を改善できます。
if( GoogleID != getStoredGoodleID($sid) ) return false;
if( byte_difference(FingerPrintID, getStoredFingerprint($sid) > 10%) return false;