Riconoscimento utente senza cookie o archiviazione locale

Sto creando uno strumento analitico e attualmente posso ottenere l’indirizzo IP dell’utente, il browser e il sistema operativo dal loro agente utente.

Mi chiedo se esiste la possibilità di rilevare lo stesso utente senza utilizzare i cookie o la memoria locale? Non mi aspetto esempi di codice qui; solo un semplice suggerimento su dove guardare oltre.

Hai dimenticato di dire che dovrebbe essere compatibile con browser diversi se si tratta dello stesso computer / dispositivo. Fondamentalmente sono in cerca del riconoscimento del dispositivo non proprio l’utente.

introduzione

Se ti capisco correttamente, devi identificare un utente per il quale non hai un identificatore univoco, quindi vuoi capire chi sono abbinando i dati casuali. Non è ansible memorizzare l’id quadro dell’utente in modo affidabile perché:

  • I cookie possono essere cancellati
  • Indirizzo IP può cambiare
  • Il browser può cambiare
  • La cache del browser potrebbe essere cancellata

Un’applet Java o un Com Object sarebbe stata una soluzione semplice utilizzando un hash di informazioni sull’hardware, ma al giorno d’oggi le persone sono così attente alla sicurezza che sarebbe difficile convincere la gente a installare questi tipi di programmi sul proprio sistema. Questo ti lascia bloccato con l’utilizzo di cookie e altri strumenti simili.

Biscotti e altri strumenti simili

Potresti prendere in considerazione la creazione di un profilo dati, quindi utilizzare i test di probabilità per identificare un utente probabile . Un profilo utile per questo può essere generato da una combinazione di quanto segue:

  1. Indirizzo IP
    • Indirizzo IP reale
    • Indirizzo IP proxy (gli utenti utilizzano spesso lo stesso proxy ripetutamente)
  2. Biscotti
    • Cookie HTTP
    • Cookie di sessione
    • Cookie di terze parti
    • Cookie Flash (la maggior parte delle persone non sa come eliminarli )
  3. Web Bug (meno affidabili perché i bug vengono corretti, ma comunque utili)
    • Bug PDF
    • Bug di Flash
    • Bug Java
  4. browser
    • Tracciamento dei clic (molti utenti visitano la stessa serie di pagine per ogni visita)
    • Fingerprint del browser – Plugin installati (le persone hanno spesso set di plug-in vari e un po ‘unici)
    • Immagini in cache (a volte le persone cancellano i loro cookie ma lasciano immagini in cache)
    • Utilizzo di BLOB
    • URL (s) (cronologia del browser o cookie possono contenere URL di ID utente univoci, come https://stackoverflow.com/users/1226894 o http://www.facebook.com/barackobama?fref=ts )
    • Rilevamento di caratteri di sistema (questa è una firma di chiave poco conosciuta ma spesso unica)
  5. HTML5 e Javascript
    • HTML5 LocalStorage
    • API di geolocalizzazione HTML5 e geocoding inverso
    • Architettura, linguaggio del sistema operativo, ora del sistema, risoluzione dello schermo, ecc.
    • API di informazioni di rete
    • API dello stato della batteria

Gli articoli che ho elencato sono, naturalmente, solo alcuni dei possibili modi in cui un utente può essere identificato in modo univoco. Ce ne sono molti altri

Con questo set di elementi di dati casuali per creare un profilo dati da, quali sono le prospettive?

Il passo successivo è sviluppare alcune Fuzzy Logic o, meglio ancora, una rete neurale artificiale (che usa la logica fuzzy). In entrambi i casi, l’idea è di addestrare il tuo sistema, e quindi combinare la sua formazione con Bayesian Inference per aumentare la precisione dei risultati.

Rete neurale artificiale

La libreria NeuralMesh per PHP ti consente di generare reti neurali artificiali. Per implementare l’inferenza bayesiana, controlla i seguenti link:

  • Implementare l’inferenza bayesiana usando PHP, parte 1
  • Implementare l’inferenza bayesiana usando PHP, parte 2
  • Implementare l’inferenza bayesiana usando PHP, parte 3

A questo punto, potresti pensare:

Perché così tanto matematica e logica per un compito apparentemente semplice?

Fondamentalmente, perché non è un compito semplice . Quello che stai cercando di ottenere è, in effetti, Pure Probability . Ad esempio, dati i seguenti utenti noti:

User1 = A + B + C + D + G + K User2 = C + D + I + J + K + F 

Quando ricevi i seguenti dati:

 B + C + E + G + F + K 

La domanda che stai essenzialmente chiedendo è:

Qual è la probabilità che i dati ricevuti (B + C + E + G + F + K) siano in realtà Utente1 o Utente2? E quale di queste due partite è più probabile?

Per rispondere efficacemente a questa domanda, è necessario comprendere il formato frequenza vs probabilità e perché la probabilità congiunta potrebbe essere un approccio migliore. I dettagli sono troppi per entrare qui (che è il motivo per cui ti sto dando link), ma un buon esempio potrebbe essere una procedura guidata di diagnosi medica , che utilizza una combinazione di sintomi per identificare possibili malattie.

Pensa per un momento alla serie di punti dati che comprendono il tuo profilo dati (B + C + E + G + F + K nell’esempio sopra) come sintomi e utenti sconosciuti come malattie . Identificando la malattia, è ansible identificare ulteriormente un trattamento appropriato (trattare questo utente come Utente1).

Ovviamente, una malattia per cui abbiamo identificato più di 1 sintomo è più facile da identificare. Infatti, più sono i sintomi che possiamo identificare, più facile e più accurata è la nostra diagnosi.

Ci sono altre alternative?

Ovviamente. Come misura alternativa, potresti creare il tuo algoritmo di punteggio semplice e basarlo su corrispondenze esatte. Questo non è efficiente quanto la probabilità, ma potrebbe essere più semplice da implementare.

Ad esempio, considera questo semplice grafico di punteggio:

 + ------------------------- + -------- + ------------ +
 |  Proprietà |  Peso |  Importanza |
 + ------------------------- + -------- + ------------ +
 |  Indirizzo IP reale |  60 |  5 |
 |  Indirizzo IP proxy utilizzato |  40 |  4 |
 |  Cookie HTTP |  80 |  8 |
 |  Cookie di sessione |  80 |  6 |
 |  Cookie di terze parti |  60 |  4 |
 |  Cookie Flash |  90 |  7 |
 |  Bug PDF  20 |  1 |
 |  Flash Bug |  20 |  1 |
 |  Bug Java |  20 |  1 |
 |  Pagine frequenti |  40 |  1 |
 |  Stampa dito del browser |  35 |  2 |
 |  Plugin installati |  25 |  1 |
 |  Immagini memorizzate nella cache |  40 |  3 |
 |  URL |  60 |  4 |
 |  Rilevamento dei caratteri di sistema |  70 |  4 |
 |  Localstorage |  90 |  8 |
 |  Geolocalizzazione |  70 |  6 |
 |  AOLTR |  70 |  4 |
 |  API di informazioni di rete |  40 |  3 |
 |  API dello stato della batteria |  20 |  1 |
 + ------------------------- + -------- + ------------ +

Per ogni informazione che puoi raccogliere su una determinata richiesta, assegna il punteggio associato, quindi usa l’ Importanza per risolvere i conflitti quando i punteggi sono gli stessi.

Verifica teorica

Per una semplice dimostrazione del concetto, per favore guarda Percetttron . Perceptron è un modello di RNA generalmente utilizzato nelle applicazioni di riconoscimento di schemi. Esiste anche una vecchia class PHP che la implementa perfettamente, ma probabilmente dovresti modificarla per i tuoi scopi.

Nonostante sia un ottimo strumento, Perceptron può ancora restituire più risultati (possibili corrispondenze), quindi utilizzare un confronto tra punteggio e differenza è comunque utile per identificare il meglio di tali incontri.

ipotesi

  • Memorizza tutte le informazioni possibili su ciascun utente (IP, cookie, ecc.)
  • Dove il risultato è una corrispondenza esatta, aumenta il punteggio di 1
  • Dove il risultato non è una corrispondenza esatta, diminuire il punteggio di 1

aspettativa

  1. Genera etichette RNA
  2. Genera utenti casuali che emulano un database
  3. Genera un singolo utente sconosciuto
  4. Genera RNA utente e valori sconosciuti
  5. Il sistema unirà le informazioni sull’RNA e insegnerà al Perceptron
  6. Dopo aver addestrato il Perceptron, il sistema avrà una serie di ponderazioni
  7. Ora puoi testare il pattern dell’utente sconosciuto e il Perceptron produrrà un set di risultati.
  8. Memorizza tutte le partite positive
  9. Ordina le partite prima per Punteggio, poi per Differenza (come descritto sopra)
  10. Mostra le due corrispondenze più vicine o, se non vengono trovate corrispondenze, genera risultati vuoti

Codice per la prova del concetto

 $features = array( 'Real IP address' => .5, 'Used proxy IP address' => .4, 'HTTP Cookies' => .9, 'Session Cookies' => .6, '3rd Party Cookies' => .6, 'Flash Cookies' => .7, 'PDF Bug' => .2, 'Flash Bug' => .2, 'Java Bug' => .2, 'Frequent Pages' => .3, 'Browsers Finger Print' => .3, 'Installed Plugins' => .2, 'URL' => .5, 'Cached PNG' => .4, 'System Fonts Detection' => .6, 'Localstorage' => .8, 'Geolocation' => .6, 'AOLTR' => .4, 'Network Information API' => .3, 'Battery Status API' => .2 ); // Get RNA Lables $labels = array(); $n = 1; foreach ($features as $k => $v) { $labels[$k] = "x" . $n; $n ++; } // Create Users $users = array(); for($i = 0, $name = "A"; $i < 5; $i ++, $name ++) { $users[] = new Profile($name, $features); } // Generate Unknown User $unknown = new Profile("Unknown", $features); // Generate Unknown RNA $unknownRNA = array( 0 => array("o" => 1), 1 => array("o" => - 1) ); // Create RNA Values foreach ($unknown->data as $item => $point) { $unknownRNA[0][$labels[$item]] = $point; $unknownRNA[1][$labels[$item]] = (- 1 * $point); } // Start Perception Class $perceptron = new Perceptron(); // Train Results $trainResult = $perceptron->train($unknownRNA, 1, 1); // Find matches foreach ($users as $name => &$profile) { // Use shorter labels $data = array_combine($labels, $profile->data); if ($perceptron->testCase($data, $trainResult) == true) { $score = $diff = 0; // Determing the score and diffrennce foreach ($unknown->data as $item => $found) { if ($unknown->data[$item] === $profile->data[$item]) { if ($profile->data[$item] > 0) { $score += $features[$item]; } else { $diff += $features[$item]; } } } // Ser score and diff $profile->setScore($score, $diff); $matchs[] = $profile; } } // Sort bases on score and Output if (count($matchs) > 1) { usort($matchs, function ($a, $b) { // If score is the same use diffrence if ($a->score == $b->score) { // Lower the diffrence the better return $a->diff == $b->diff ? 0 : ($a->diff > $b->diff ? 1 : - 1); } // The higher the score the better return $a->score > $b->score ? - 1 : 1; }); echo "
Possible Match ", implode(",", array_slice(array_map(function ($v) { return sprintf(" %s (%0.4f|%0.4f) ", $v->name, $v->score,$v->diff); }, $matchs), 0, 2)); } else { echo "
No match Found "; }

Produzione:

 Possible Match D (0.7416|0.16853),C (0.5393|0.2809) 

Stampa_r di “D”:

 echo "
"; print_r($matchs[0]); Profile Object( [name] => D [data] => Array ( [Real IP address] => -1 [Used proxy IP address] => -1 [HTTP Cookies] => 1 [Session Cookies] => 1 [3rd Party Cookies] => 1 [Flash Cookies] => 1 [PDF Bug] => 1 [Flash Bug] => 1 [Java Bug] => -1 [Frequent Pages] => 1 [Browsers Finger Print] => -1 [Installed Plugins] => 1 [URL] => -1 [Cached PNG] => 1 [System Fonts Detection] => 1 [Localstorage] => -1 [Geolocation] => -1 [AOLTR] => 1 [Network Information API] => -1 [Battery Status API] => -1 ) [score] => 0.74157303370787 [diff] => 0.1685393258427 [base] => 8.9 )

Se Debug = true, è ansible visualizzare Input (Sensor & Desired), Initial Weights, Output (Sensor, Sum, Network), Error, Correction e Final Weights .

 +----+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+-----+----+---------+---------+---------+---------+---------+---------+---------+---------+---------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----------+ | o | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15 | x16 | x17 | x18 | x19 | x20 | Bias | Yin | Y | deltaW1 | deltaW2 | deltaW3 | deltaW4 | deltaW5 | deltaW6 | deltaW7 | deltaW8 | deltaW9 | deltaW10 | deltaW11 | deltaW12 | deltaW13 | deltaW14 | deltaW15 | deltaW16 | deltaW17 | deltaW18 | deltaW19 | deltaW20 | W1 | W2 | W3 | W4 | W5 | W6 | W7 | W8 | W9 | W10 | W11 | W12 | W13 | W14 | W15 | W16 | W17 | W18 | W19 | W20 | deltaBias | +----+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+-----+----+---------+---------+---------+---------+---------+---------+---------+---------+---------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----------+ | 1 | 1 | -1 | -1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 0 | -1 | 0 | -1 | -1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | -1 | -1 | -1 | -1 | 1 | 1 | 0 | -1 | -1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | | -1 | -1 | 1 | 1 | 1 | 1 | 1 | 1 | -1 | -1 | -1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 1 | -1 | -1 | 1 | -19 | -1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -1 | -1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | | 1 | 1 | -1 | -1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 19 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -1 | -1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | | -1 | -1 | 1 | 1 | 1 | 1 | 1 | 1 | -1 | -1 | -1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 1 | -1 | -1 | 1 | -19 | -1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -1 | -1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | -1 | -1 | -1 | -1 | 1 | 1 | 1 | | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | +----+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+-----+----+---------+---------+---------+---------+---------+---------+---------+---------+---------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----------+ 

da x1 a x20 rappresentano le caratteristiche convertite dal codice.

 // Get RNA Labels $labels = array(); $n = 1; foreach ( $features as $k => $v ) { $labels[$k] = "x" . $n; $n ++; } 

Ecco una demo online

Classe utilizzata:

 class Profile { public $name, $data = array(), $score, $diff, $base; function __construct($name, array $importance) { $values = array(-1, 1); // Perception values $this->name = $name; foreach ($importance as $item => $point) { // Generate Random true/false for real Items $this->data[$item] = $values[mt_rand(0, 1)]; } $this->base = array_sum($importance); } public function setScore($score, $diff) { $this->score = $score / $this->base; $this->diff = $diff / $this->base; } } 

Classe Perceptron modificata

 class Perceptron { private $w = array(); private $dw = array(); public $debug = false; private function initialize($colums) { // Initialize perceptron vars for($i = 1; $i <= $colums; $i ++) { // weighting vars $this->w[$i] = 0; $this->dw[$i] = 0; } } function train($input, $alpha, $teta) { $colums = count($input[0]) - 1; $weightCache = array_fill(1, $colums, 0); $checkpoints = array(); $keepTrainning = true; // Initialize RNA vars $this->initialize(count($input[0]) - 1); $just_started = true; $totalRun = 0; $yin = 0; // Trains RNA until it gets stable while ($keepTrainning == true) { // Sweeps each row of the input subject foreach ($input as $row_counter => $row_data) { // Finds out the number of columns the input has $n_columns = count($row_data) - 1; // Calculates Yin $yin = 0; for($i = 1; $i <= $n_columns; $i ++) { $yin += $row_data["x" . $i] * $weightCache[$i]; } // Calculates Real Output $Y = ($yin <= 1) ? - 1 : 1; // Sweeps columns ... $checkpoints[$row_counter] = 0; for($i = 1; $i <= $n_columns; $i ++) { /** DELTAS **/ // Is it the first row? if ($just_started == true) { $this->dw[$i] = $weightCache[$i]; $just_started = false; // Found desired output? } elseif ($Y == $row_data["o"]) { $this->dw[$i] = 0; // Calculates Delta Ws } else { $this->dw[$i] = $row_data["x" . $i] * $row_data["o"]; } /** WEIGHTS **/ // Calculate Weights $this->w[$i] = $this->dw[$i] + $weightCache[$i]; $weightCache[$i] = $this->w[$i]; /** CHECK-POINT **/ $checkpoints[$row_counter] += $this->w[$i]; } // END - for foreach ($this->w as $index => $w_item) { $debug_w["W" . $index] = $w_item; $debug_dw["deltaW" . $index] = $this->dw[$index]; } // Special for script debugging $debug_vars[] = array_merge($row_data, array( "Bias" => 1, "Yin" => $yin, "Y" => $Y ), $debug_dw, $debug_w, array( "deltaBias" => 1 )); } // END - foreach // Special for script debugging $empty_data_row = array(); for($i = 1; $i <= $n_columns; $i ++) { $empty_data_row["x" . $i] = "--"; $empty_data_row["W" . $i] = "--"; $empty_data_row["deltaW" . $i] = "--"; } $debug_vars[] = array_merge($empty_data_row, array( "o" => "--", "Bias" => "--", "Yin" => "--", "Y" => "--", "deltaBias" => "--" )); // Counts training times $totalRun ++; // Now checks if the RNA is stable already $referer_value = end($checkpoints); // if all rows match the desired output ... $sum = array_sum($checkpoints); $n_rows = count($checkpoints); if ($totalRun > 1 && ($sum / $n_rows) == $referer_value) { $keepTrainning = false; } } // END - while // Prepares the final result $result = array(); for($i = 1; $i <= $n_columns; $i ++) { $result["w" . $i] = $this->w[$i]; } $this->debug($this->print_html_table($debug_vars)); return $result; } // END - train function testCase($input, $results) { // Sweeps input columns $result = 0; $i = 1; foreach ($input as $column_value) { // Calculates teste Y $result += $results["w" . $i] * $column_value; $i ++; } // Checks in each class the test fits return ($result > 0) ? true : false; } // END - test_class // Returns the html code of a html table base on a hash array function print_html_table($array) { $html = ""; $inner_html = ""; $table_header_composed = false; $table_header = array(); // Builds table contents foreach ($array as $array_item) { $inner_html .= "\n"; foreach ( $array_item as $array_col_label => $array_col ) { $inner_html .= "\n"; $inner_html .= $array_col; $inner_html .= "\n"; if ($table_header_composed == false) { $table_header[] = $array_col_label; } } $table_header_composed = true; $inner_html .= "\n"; } // Builds full table $html = "\n"; $html .= "\n"; foreach ($table_header as $table_header_item) { $html .= "\n"; } $html .= "\n"; $html .= $inner_html . "
\n"; $html .= "" . $table_header_item . ""; $html .= "
"; return $html; } // END - print_html_table // Debug function function debug($message) { if ($this->debug == true) { echo "DEBUG: $message"; } } // END - debug } // END - class

Conclusione

Identificare un utente senza un identificatore univoco non è un'attività semplice o semplice. dipende dalla raccolta di una quantità sufficiente di dati casuali che è ansible raccogliere dall'utente con una varietà di metodi.

Anche se scegli di non usare una rete neurale artificiale, suggerisco almeno di utilizzare una matrice di probabilità semplice con priorità e probabilità - e spero che il codice e gli esempi sopra forniti ti diano abbastanza per andare avanti.

Questa tecnica (per rilevare gli stessi utenti senza cookie – o anche senza indirizzo ip) è chiamata fingerprinting del browser . Fondamentalmente si esegue la scansione delle informazioni sul browser che è ansible: risultati migliori possono essere ottenuti con javascript, flash o java (ad esempio estensioni installate, font, ecc.). Successivamente, è ansible memorizzare l’hash dei risultati, se lo si desidera.

Non è infallibile, ma:

L’83,6% dei browser visualizzati aveva un’impronta digitale unica; tra quelli con Flash o Java abilitati, il 94,2%. Questo non include i cookie!

Ulteriori informazioni:

L’identificazione di cui sopra funziona, ma può ancora soffrire di collisioni.

Un modo è aggiungere UID all’URL di ogni interazione con l’utente.

http://someplace.com/12899823/user/profile

Dove ogni link nel sito è adattato con questo modificatore. È simile al modo in cui ASP.Net utilizzava i dati FORM tra le pagine.

Hai esaminato Evercookie ? Potrebbe funzionare o meno nei vari browser. Un estratto dal loro sito.

“Se un utente viene cucinato su un browser e passa a un altro browser, purché continui ad avere il cookie Local Shared Object, il cookie verrà riprodotto in entrambi i browser.”

È ansible farlo con un png memorizzato nella cache, sarebbe in qualche modo inaffidabile (i diversi browser si comportano diversamente e fallirà se l’utente cancella la cache), ma è un’opzione.

1: imposta un database che memorizza un ID utente univoco come stringa esadecimale

2: crea un file https://stackoverflow.com/questions/15966812/user-recognition-without-cookies-or-local-storage/genUser.php (o qualsiasi altra lingua) che genera un id utente, lo memorizza nel DB e crea un vero colore .png fuori dai valori di quella stringa esadecimale (ogni pixel sarà di 4 byte) e restituisce quello al browser. Assicurati di impostare il tipo di contenuto e le intestazioni della cache.

3: in HTML o JS creare un’immagine come

4: disegnare quell’immagine su una canvas ctx.drawImage(document.getElementById('user_id'), 0, 0);

5: leggi i byte di quell’immagine usando ctx.getImageData e converti i numeri interi in una stringa esadecimale.

6: Questo è il tuo ID utente unico che ora è memorizzato nella cache sul tuo computer degli utenti.

In base a ciò che hai detto:

Fondamentalmente sono in cerca del riconoscimento del dispositivo non proprio l’utente

Il modo migliore per farlo è inviare l’indirizzo mac che è l’ID NIC.

Puoi dare un’occhiata a questo post: Come posso ottenere il MAC e l’indirizzo IP di un client connesso in PHP?

JavaScript Mac Finder

Puoi farlo con gli etags. Anche se non sono sicuro se questo legale come un mucchio di cause legali sono state presentate.

Se avvisi correttamente i tuoi utenti o se hai qualcosa come un sito intranet, potrebbe essere ok.

Potresti potenzialmente creare un blob per memorizzare un identificativo del dispositivo …

il lato negativo è che l’utente deve scaricare il blob ( è ansible forzare il download ), poiché il browser non può accedere al File System per salvare direttamente il file.

riferimento:

https://www.inkling.com/read/javascript-definitive-guide-david-flanagan-6th/chapter-22/blobs

Inefficiente, ma potrebbe darti i risultati desiderati, sarebbe il sondaggio di un’API dalla tua parte. Avere un processo in background sul lato client che manda i dati dell’utente a intervalli. Avrai bisogno di un identificativo utente da inviare alla tua API. Una volta che hai puoi inviare tutte le informazioni associate a quell’identificativo univoco.

Ciò elimina la necessità di cookie e localstorage.

Non ci posso credere, http://browserspy.dk non è ancora stato menzionato qui! Il sito descrive molte funzionalità (in termini di riconoscimento dei pattern), che potrebbero essere utilizzate per build un classificatore.

E di causa, per valutare le funzionalità suggerirei Support Vector Machines e libsvm in particolare.

Tracciali durante una sessione o attraverso le sessioni?

Se il tuo sito è HTTPS Ovunque, puoi utilizzare l’ID sessione TLS per tenere traccia della sessione dell’utente

  1. creare un plugin fittizio multipiattaforma (nsapi) e generare un nome univoco per il nome o la versione del plugin quando l’utente lo scarica (ad es. dopo il login).
  2. fornire un programma di installazione per il plug-in / installarlo per policy

questo richiederà all’utente di installare volontariamente l’identificatore.

una volta installato il plug-in, l’ impronta digitale di qualsiasi browser (abilitato per il plugin) conterrà questo plug-in specifico. Per restituire le informazioni a un server, è necessario un algoritmo per rilevare efficacemente il plug-in sul lato client, altrimenti IE e Firefox> = 28 utenti avranno bisogno di una tabella di possibili identificativi validi.

Ciò richiede un investimento relativamente elevato in una tecnologia che verrà probabilmente chiusa dai fornitori di browser. Quando sei in grado di convincere i tuoi utenti a installare un plug-in, potrebbero esserci anche opzioni come installare un proxy locale , utilizzare VPN o patch dei driver di rete.

Gli utenti che non vogliono essere identificati (o le loro macchine) troveranno sempre un modo per prevenirlo.