Benutzererkennung ohne Cookies oder lokalen Speicher


132

Ich erstelle ein Analysetool und kann derzeit die IP-Adresse, den Browser und das Betriebssystem des Benutzers von seinem Benutzeragenten abrufen.

Ich frage mich, ob es eine Möglichkeit gibt, denselben Benutzer zu erkennen, ohne Cookies oder lokalen Speicher zu verwenden. Ich erwarte hier keine Codebeispiele. nur ein einfacher Hinweis, wo man weiter suchen muss.

Ich habe vergessen zu erwähnen, dass es browserübergreifend kompatibel sein muss, wenn es sich um denselben Computer / dasselbe Gerät handelt. Grundsätzlich bin ich nach Geräteerkennung nicht wirklich der Benutzer.


5
Nicht wirklich - zumindest nicht auf eine Weise, auf die man sich verlassen kann, um genau zu sein. Vielleicht ein Hash von allen dreien zusammen, aber wenn mehr als eine Person in einem Haus denselben Browser und dasselbe Betriebssystem verwendet, würde es immer noch nicht funktionieren. Außerdem stellen die meisten ISPs dynamische IP-Adressen bereit, was bedeutet, dass sie sich von Zeit zu Zeit ändern und auch nicht zu Identifikationszwecken herangezogen werden können.
Jon

2
Dann wissen Sie nicht, was Sitzungen sind. Ihr Anwendungsfall ist genau das, wofür Sitzungen entwickelt wurden. Sitzungen haben nichts mit Anmeldung oder Authentifizierung zu tun. Ihr Webserver weist einen Client an, ein Cookie mit einer Sitzungskennung zu senden. Sie identifizieren diesen Client anhand der Sitzungs-ID, die er Ihnen sendet.
Mann gegen Code

4
Cookies würden immer noch funktionieren? Warum vermeiden Sie die Verwendung von Cookies?
Baba

2
Es ist wirklich einfach und ich benutze es die ganze Zeit. Bitten Sie den Benutzer, einen Benutzernamen und ein Passwort einzugeben !!!
Amit Kriplani

2
Hier ist eine minimale Javascript-Lösung (in diesem Fall nicht browserübergreifend): github.com/carlo/jquery-browser-fingerprint Ich erwähne es, weil ich auf die Idee kam, dass viele Plugins standardmäßig browserübergreifend ohne installiert werden jede Wahl des Benutzers. Eine sorgfältige Sortierung (was keine kleine Aufgabe ist, aber dennoch ...) kann möglicherweise zu einer spürbaren browserunabhängigen Eigenschaft eines größeren gerätebasierten Fingerabdrucks führen.
Hexalys

Antworten:


389

Einführung

Wenn ich Sie richtig verstehe, müssen Sie einen Benutzer identifizieren, für den Sie keine eindeutige Kennung haben. Sie möchten also herausfinden, wer er ist, indem Sie zufällige Daten abgleichen. Sie können die Identität des Benutzers nicht zuverlässig speichern, weil:

  • Cookies können gelöscht werden
  • IP-Adresse Kann sich ändern
  • Browser kann sich ändern
  • Der Browser-Cache wird möglicherweise gelöscht

Ein Java-Applet oder Com-Objekt wäre eine einfache Lösung mit einem Hash von Hardwareinformationen gewesen, aber heutzutage sind die Benutzer so sicherheitsbewusst, dass es schwierig ist, Benutzer dazu zu bringen, diese Art von Programmen auf ihrem System zu installieren. Dies führt dazu, dass Sie keine Cookies und andere ähnliche Tools verwenden müssen.

Cookies und andere ähnliche Tools

Sie können ein Datenprofil erstellen und dann mithilfe von Wahrscheinlichkeitstests einen wahrscheinlichen Benutzer identifizieren . Ein hierfür nützliches Profil kann durch eine Kombination der folgenden Elemente erstellt werden:

  1. IP Adresse
    • Echte IP-Adresse
    • Proxy-IP-Adresse (Benutzer verwenden häufig denselben Proxy wiederholt)
  2. Kekse
  3. Web-Fehler (weniger zuverlässig, da Fehler behoben werden, aber dennoch nützlich sind)
    • PDF Bug
    • Flash Bug
    • Java Bug
  4. Browser
    • Klicken Sie auf Tracking (viele Benutzer besuchen bei jedem Besuch dieselbe Seitenreihe).
    • Browser Fingerabdruck - Installierte Plugins (Menschen haben oft unterschiedliche, etwas einzigartige Sätze von Plugins)
    • Zwischengespeicherte Bilder (Leute löschen manchmal ihre Cookies, lassen aber zwischengespeicherte Bilder)
    • Blobs verwenden
    • URL (s) (Browserverlauf oder Cookies können eindeutige Benutzer-IDs in URLs enthalten, z. B. https://stackoverflow.com/users/1226894 oder http://www.facebook.com/barackobama?fref=ts )
    • Erkennung von Systemschriftarten (dies ist eine wenig bekannte, aber häufig eindeutige Schlüsselsignatur)
  5. HTML5 & Javascript
    • HTML5 LocalStorage
    • HTML5 Geolocation API und Reverse Geocoding
    • Architektur, Betriebssystemsprache, Systemzeit, Bildschirmauflösung usw.
    • Netzwerkinformations-API
    • Batteriestatus-API

Die von mir aufgelisteten Elemente sind natürlich nur einige Möglichkeiten, wie ein Benutzer eindeutig identifiziert werden kann. Es gibt viele mehr.

Wie geht es mit diesem Satz zufälliger Datenelemente weiter, aus denen ein Datenprofil erstellt werden soll?

Der nächste Schritt ist die Entwicklung einer Fuzzy-Logik oder, noch besser, eines künstlichen neuronalen Netzwerks (das Fuzzy-Logik verwendet). In beiden Fällen besteht die Idee darin, Ihr System zu trainieren und dann sein Training mit Bayesian Inference zu kombinieren , um die Genauigkeit Ihrer Ergebnisse zu erhöhen.

Künstliche neuronale Netz

Mit der NeuralMesh- Bibliothek für PHP können Sie künstliche neuronale Netze generieren. Überprüfen Sie die folgenden Links, um die Bayes'sche Inferenz zu implementieren:

An diesem Punkt denken Sie vielleicht:

Warum so viel Mathematik und Logik für eine scheinbar einfache Aufgabe?

Grundsätzlich, weil es keine einfache Aufgabe ist . Was Sie erreichen möchten, ist in der Tat reine Wahrscheinlichkeit . Zum Beispiel bei folgenden bekannten Benutzern:

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

Wenn Sie folgende Daten erhalten:

B + C + E + G + F + K

Die Frage, die Sie im Wesentlichen stellen, lautet:

Wie groß ist die Wahrscheinlichkeit, dass die empfangenen Daten (B + C + E + G + F + K) tatsächlich Benutzer1 oder Benutzer2 sind? Und welches dieser beiden Spiele ist am wahrscheinlichsten?

Um diese Frage effektiv beantworten zu können, müssen Sie das Format Frequenz gegen Wahrscheinlichkeit verstehen und wissen, warum die gemeinsame Wahrscheinlichkeit ein besserer Ansatz sein könnte. Die Details sind zu umfangreich, um hier näher darauf einzugehen (weshalb ich Ihnen Links gebe), aber ein gutes Beispiel wäre eine Anwendung des Assistenten für medizinische Diagnosen , die eine Kombination von Symptomen verwendet, um mögliche Krankheiten zu identifizieren.

Stellen Sie sich für einen Moment die Reihe von Datenpunkten vor, aus denen Ihr Datenprofil (B + C + E + G + F + K im obigen Beispiel) als Symptome und unbekannte Benutzer als Krankheiten besteht . Indem Sie die Krankheit identifizieren, können Sie eine geeignete Behandlung identifizieren (behandeln Sie diesen Benutzer als Benutzer1).

Offensichtlich ist eine Krankheit, für die wir mehr als ein Symptom identifiziert haben, leichter zu identifizieren. Je mehr Symptome wir identifizieren können, desto einfacher und genauer ist unsere Diagnose.

Gibt es noch andere Alternativen?

Natürlich. Als alternative Maßnahme können Sie Ihren eigenen einfachen Bewertungsalgorithmus erstellen und ihn auf exakten Übereinstimmungen basieren. Dies ist nicht so effizient wie die Wahrscheinlichkeit, kann jedoch für Sie einfacher zu implementieren sein.

Betrachten Sie als Beispiel diese einfache Punktetabelle:

+ ------------------------- + -------- + ------------ +
| Eigentum | Gewicht | Bedeutung |
+ ------------------------- + -------- + ------------ +
| Echte IP-Adresse | 60 | 5 |
| Verwendete Proxy-IP-Adresse | 40 | 4 |
| HTTP-Cookies | 80 | 8 |
| Sitzungscookies | 80 | 6 |
| Cookies von Drittanbietern | 60 | 4 |
| Flash-Cookies | 90 | 7 |
| PDF Bug | 20 | 1 |
| Flash Bug | 20 | 1 |
| Java Bug | 20 | 1 |
| Häufige Seiten | 40 | 1 |
| Browser Fingerabdruck | 35 | 2 |
| Installierte Plugins | 25 | 1 |
| Zwischengespeicherte Bilder | 40 | 3 |
| URL | 60 | 4 |
| Systemschriftartenerkennung | 70 | 4 |
| Localstorage | 90 | 8 |
| Geolocation | 70 | 6 |
| AOLTR | 70 | 4 |
| Netzwerkinformations-API | 40 | 3 |
| Batteriestatus-API | 20 | 1 |
+ ------------------------- + -------- + ------------ +

Vergeben Sie für jede Information, die Sie auf eine bestimmte Anfrage sammeln können, die zugehörige Punktzahl und verwenden Sie dann Wichtigkeit , um Konflikte zu lösen, wenn die Punktzahlen gleich sind.

Konzeptioneller Beweiß

Für einen einfachen Proof of Concept werfen Sie bitte einen Blick auf Perceptron . Perceptron ist ein RNA-Modell , das im Allgemeinen in Mustererkennungsanwendungen verwendet wird. Es gibt sogar eine alte PHP-Klasse, die sie perfekt implementiert, aber Sie müssten sie wahrscheinlich für Ihre Zwecke ändern.

Obwohl Perceptron ein großartiges Tool ist, kann es dennoch mehrere Ergebnisse (mögliche Übereinstimmungen) zurückgeben. Daher ist die Verwendung eines Vergleichs von Punktzahl und Differenz immer noch nützlich, um die besten dieser Übereinstimmungen zu ermitteln.

Annahmen

  • Speichern Sie alle möglichen Informationen zu jedem Benutzer (IP, Cookies usw.).
  • Wenn das Ergebnis genau übereinstimmt, erhöhen Sie die Punktzahl um 1
  • Wenn das Ergebnis nicht exakt übereinstimmt, verringern Sie die Punktzahl um 1

Erwartung

  1. RNA-Markierungen generieren
  2. Generieren Sie zufällige Benutzer, die eine Datenbank emulieren
  3. Generieren Sie einen einzelnen unbekannten Benutzer
  4. Generieren Sie unbekannte Benutzer-RNA und -Werte
  5. Das System wird RNA-Informationen zusammenführen und das Perceptron lehren
  6. Nach dem Training des Perceptron hat das System eine Reihe von Gewichtungen
  7. Sie können jetzt das Muster des unbekannten Benutzers testen und das Perceptron erstellt eine Ergebnismenge.
  8. Speichern Sie alle positiven Übereinstimmungen
  9. Sortieren Sie die Übereinstimmungen zuerst nach Punktzahl und dann nach Differenz (wie oben beschrieben).
  10. Geben Sie die zwei engsten Übereinstimmungen aus oder geben Sie leere Ergebnisse aus, wenn keine Übereinstimmungen gefunden werden

Code für Proof of Concept

$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 "<br />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 "<br />No match Found ";
}

Ausgabe:

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

Print_r von "D":

echo "<pre>";
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
)

Wenn Debug = true, können Sie Eingabe (Sensor & Gewünscht), Anfangsgewichte, Ausgabe (Sensor, Summe, Netzwerk), Fehler, Korrektur und Endgewichte anzeigen .

+----+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+-----+----+---------+---------+---------+---------+---------+---------+---------+---------+---------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----------+
| 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         |
| -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | --  | --  | --  | --  | --  | --  | --  | --  | --  | --  | --  | --   | --  | -- | --      | --      | --      | --      | --      | --      | --      | --      | --      | --       | --       | --       | --       | --       | --       | --       | --       | --       | --       | --       | -- | -- | -- | -- | -- | -- | -- | -- | -- | --  | --  | --  | --  | --  | --  | --  | --  | --  | --  | --  | --        |
+----+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+-----+----+---------+---------+---------+---------+---------+---------+---------+---------+---------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----------+

x1 bis x20 repräsentieren die vom Code konvertierten Features.

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

Hier ist eine Online-Demo

Verwendete Klasse:

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;
    }
}

Modifizierte Perceptron-Klasse

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 .= "<tr>\n";
            foreach ( $array_item as $array_col_label => $array_col ) {
                $inner_html .= "<td>\n";
                $inner_html .= $array_col;
                $inner_html .= "</td>\n";

                if ($table_header_composed == false) {
                    $table_header[] = $array_col_label;
                }
            }
            $table_header_composed = true;
            $inner_html .= "</tr>\n";
        }

        // Builds full table
        $html = "<table border=1>\n";
        $html .= "<tr>\n";
        foreach ($table_header as $table_header_item) {
            $html .= "<td>\n";
            $html .= "<b>" . $table_header_item . "</b>";
            $html .= "</td>\n";
        }
        $html .= "</tr>\n";

        $html .= $inner_html . "</table>";

        return $html;
    } // END - print_html_table

    // Debug function
    function debug($message) {
        if ($this->debug == true) {
            echo "<b>DEBUG:</b> $message";
        }
    } // END - debug
} // END - class

Fazit

Das Identifizieren eines Benutzers ohne eindeutige Kennung ist keine einfache oder einfache Aufgabe. Dies hängt davon ab, ob eine ausreichende Menge zufälliger Daten erfasst wird, die Sie mit verschiedenen Methoden vom Benutzer erfassen können.

Selbst wenn Sie sich dafür entscheiden, kein künstliches neuronales Netzwerk zu verwenden, empfehle ich, zumindest eine einfache Wahrscheinlichkeitsmatrix mit Prioritäten und Wahrscheinlichkeiten zu verwenden - und ich hoffe, dass der Code und die Beispiele oben Ihnen genug geben, um fortzufahren.


@Baba Was meinst du mit "Blobs verwenden", um einen Browser mit einem Fingerabdruck zu versehen?
Billmalarky


1
@Baba Wie würde man das verwenden, um einen Browser mit einem Fingerabdruck zu versehen? Überprüfen Sie einfach, was zu einem bestimmten Zeitpunkt aktuell darin ist.
Billmalarky

@Baba großartige Arbeit, ich habe immer versucht, eine mehrstufige Strategie zur Identifizierung eines Benutzers zu entwickeln, aber wie Sie sagten, kann der Cache geleert, IPs geändert, Benutzer hinter Proxies oder NAT - insbesondere diese Personen -, Cookies gelöscht usw. werden. Aber trotz all dieser Mühe ist es eine Frage der Wahrscheinlichkeit, auch wenn der schlechte Benutzer beispielsweise den Tor- Browser verwendet, funktionieren die meisten, wenn nicht alle der genannten Erkennungsstrategien nicht. Ich mochte browserleaks.com, aber mit Tor kamen alle undefiniert oder unbekannt zurück
Mi-Creativity

Nur ein Hinweis, der nur dazu gedacht ist, "etwas Staub von diesem Juwel einer Veröffentlichung zu entfernen" : Liste der defekten Links ab dem 07.09.17: - Implement Bayesian inference using PHP, alle 3 Teile. - Frequency vs Probability - Joint Probability -Input (Sensor & Desired), Initial Weights, Output (Sensor, Sum, Network), Error, Correction and Final Weights
Ziezi

28

Diese Technik (um dieselben Benutzer ohne Cookies oder sogar ohne IP-Adresse zu erkennen) wird als Browser-Fingerabdruck bezeichnet . Grundsätzlich crawlen Sie so viele Informationen wie möglich über den Browser - bessere Ergebnisse können mit Javascript, Flash oder Java erzielt werden (z. B. installierte Erweiterungen, Schriftarten usw.). Danach können Sie die gehashten Ergebnisse speichern, wenn Sie möchten.

Es ist nicht unfehlbar, aber:

83,6% der gesehenen Browser hatten einen eindeutigen Fingerabdruck. 94,2% der Benutzer mit aktiviertem Flash oder Java. Dies beinhaltet keine Cookies!

Mehr Info:


Ich denke, es ist immer noch die Antwort. Wenn Sie ein Gerät identifizieren müssen, müssen Sie nur diese Daten abrufen - z. Betriebssystem, generische Erweiterungen (und seine 'Versionen), installierte Schriftarten usw.
pozs

Das wird nicht gut funktionieren. Jeder Browser unterstützt Sitzungen und Cookies. Verwenden Sie das richtige Werkzeug für den Job.
Mann gegen Code

1
@ slash197 was ist mit Datei-Cache? Ich meine, 1px x 1px transparente Flash-Medien zusammen mit einer XML-Datei zu verwenden, die eine eindeutige generierte ID enthält (die XML sollte einmal auf dem Server erstellt werden, bevor sie auf die lokale Festplatte des Benutzers heruntergeladen wird), selbst wenn der Benutzer Cookies löscht oder sich abmeldet. Mit der sendAndLoad-Methode des Aktionsskripts können Sie weiterhin eine Bridge erstellen.
Mbarry

Das Minimum an Änderungen wirkt sich auf das Hash-Ergebnis aus. Zum Beispiel die Version des Stoßwellen-Players. Mögliche Lösung mit lokal gespeicherter XML-Cache-Datei mit eindeutigem Schlüssel generiert + versteckte 1px x 1px Flash-Medien (Aktionsskript) im Browser. Auf diese Weise werden Cookies entfernt, Sitzungsablaufproblem, wenn dies das Hauptproblem war. Sie können weiterhin die Brücke zwischen Ihrer SQL-Datenbank und dem Schlüssel auf dem lokalen Computer des Benutzers herstellen.
Mbarry

@Mbarry Ich bin kein großer Flash-Fan, aber wenn es im Browser ein Flash-Blocking-Add-On gibt, wie ich es habe, dass 1x1-Pixel-Flash-Medien deaktiviert wären, bin ich erschrocken?
Slash197

7

Der oben erwähnte Fingerabdruck funktioniert, kann aber dennoch zu Kollisionen führen.

Eine Möglichkeit besteht darin, der URL jeder Interaktion mit dem Benutzer eine UID hinzuzufügen.

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

Wobei jeder Link auf der Site mit diesem Modifikator angepasst wird. Es ähnelt der Art und Weise, wie ASP.Net mit FORM-Daten zwischen Seiten gearbeitet hat.


Ich dachte daran, aber das ist der einfachste Weg für einen Benutzer, es zu ändern
slash197

1
Nicht von der ID ist ein selbstreferenzierender Hash. Macht es kryptografisch sicher.
Justin Alexander

Diese Methode ist auch in Ordnung, wenn jemand auf der Website surft. Wie schlagen Sie jedoch vor, den Fall zu behandeln, wenn ein wiederkehrender Benutzer nach einer Woche zurückkommt und einfach die Adresse der Website ohne ID eingibt?
Slash197

@ slash197 in diesem Fall, warum sagst du dem Benutzer nicht, dass er sich anmelden soll, was passiert, selbst wenn der Benutzer die Cookies löscht?
Akash Kava

6

Hast du dir Evercookie angesehen ? Es kann in allen Browsern funktionieren oder nicht. Ein Auszug aus ihrer Website.

"Wenn ein Benutzer in einem Browser gekocht wird und zu einem anderen Browser wechselt, wird der Cookie in beiden Browsern reproduziert, solange er noch das Cookie" Lokales gemeinsames Objekt "hat."


Ich frage mich, ob es mit deaktiviertem JavaScript funktioniert. Hast du irgendwelche Erfahrung?
Voitcus

Es heißt aus einem bestimmten Grund Evercookie, es wird funktionieren, egal was passiert. Es ist nahezu unmöglich für sie, den Cookie zu entfernen.
Alexis Tyler

Es wird nicht funktionieren, egal was passiert. Aus der ersten Zeile der Beschreibung: 'evercookie ist eine Javascript-API ...'. Es wird nicht funktionieren, wenn Javascript deaktiviert ist.
GDW2

Muss nicht einmal deaktiviert sein. Ghostery und uBlock lassen Evercookie fallen
Opengrid

3

Sie könnten dies mit einem zwischengespeicherten PNG tun, es wäre etwas unzuverlässig (verschiedene Browser verhalten sich unterschiedlich und es schlägt fehl, wenn der Benutzer seinen Cache löscht), aber es ist eine Option.

1: Richten Sie eine Datenbank ein, in der eine eindeutige Benutzer-ID als Hex-Zeichenfolge gespeichert ist

2: Erstellen Sie eine genUser.php-Datei (oder eine andere Sprache), die eine Benutzer-ID generiert, diese in der Datenbank speichert und dann aus den Werten dieser Hex-Zeichenfolge eine echte Farb-PNG-Datei erstellt (jedes Pixel hat 4 Byte), und geben Sie sie zurück das an den Browser. Stellen Sie sicher, dass Sie den Inhaltstyp und die Cache-Header festlegen.

3: In HTML oder JS erstellen Sie ein Bild wie <img id='user_id' src='genUser.php' />

4: Zeichnen Sie das Bild auf eine Leinwand ctx.drawImage(document.getElementById('user_id'), 0, 0);

5: Lesen Sie die Bytes dieses Bildes mit aus ctx.getImageDataund konvertieren Sie die Ganzzahlen in eine Hex-Zeichenfolge.

6: Dies ist Ihre eindeutige Benutzer-ID, die jetzt auf dem Computer Ihres Benutzers zwischengespeichert wird.


Er möchte etwas, das den Benutzer "über Browser hinweg" verfolgen kann, was hier nicht funktioniert (jeder Browser hat seine eigene Cache-Datenbank).
EricLaw

Wo sehen Sie das? In seiner Frage wird nur gefragt: "Ich habe vergessen zu erwähnen, dass es browserübergreifend kompatibel sein muss", dh in jedem Browser funktionieren.
hobberwickey

Seine Frage ist schlecht geschrieben. I'm after device recognitionist das Werbegeschenk für das, was er will, und er arbeitet hier aus: stackoverflow.com/questions/15966812/…
EricLaw

2

Basierend auf dem, was Sie gesagt haben:

Grundsätzlich bin ich nach Geräteerkennung nicht wirklich der Benutzer

Am besten senden Sie die Mac-Adresse, die die NIC-ID ist.

Sie können sich diesen Beitrag ansehen: Wie kann ich den MAC und die IP-Adresse eines verbundenen Clients in PHP abrufen?


Entschuldigung, aber die NIC-ID ist leicht zu fälschen. Es ist definitiv nicht der beste Weg.
Asgs

@asgs Browser Fingerabdruck wäre vielleicht besser, oder was wäre Ihrer Meinung nach der beste Weg?
Mehdi Karamosly

Es gibt keinen besten Weg, das ist der traurige Teil. Dies und Browser FingerPrinting in Kombination mit der Wahrscheinlichkeitsstudie, die Baba oben vorgestellt hat, wären meiner Meinung nach die besten.
Asgs

1

Sie können es mit etags tun. Obwohl ich nicht sicher bin, ob diese rechtliche als eine Reihe von Klagen eingereicht wurden.

Wenn Sie Ihre Benutzer richtig warnen oder eine Intranet-Website haben, ist dies möglicherweise in Ordnung.


Etags sind nicht browserübergreifend kompatibel.
Slash197

1
Etags sind Teil der HTTP / 1.1-Spezifikation. Alle gängigen Browser unterstützen Etags. Sie müssten so ziemlich Ihren eigenen Browser schreiben, um ETag / If-None-Match-Header nicht zu unterstützen.
Brian McGinity

Ich habe nicht gesagt, dass es nicht unterstützt wird, ich habe gesagt, dass es nicht browserübergreifend kompatibel ist. Wenn ein Tag in Firefox gespeichert ist, ist es nicht in Chrome verfügbar, sodass der Inhalt erneut heruntergeladen wird, da kein Cache vorhanden ist.
Slash197

Jetzt verstehe ich, was du gesagt hast. Du hast recht. Jeder Browser hat einen eigenen Cache-Speicher, daher unterschiedliche Etags.
Brian McGinity


0

Ineffizient, kann aber zu den gewünschten Ergebnissen führen, wäre es, eine API auf Ihrer Seite abzufragen. Haben Sie einen Hintergrundprozess auf der Clientseite, der in regelmäßigen Abständen Benutzerdaten sendet. Sie benötigen eine Benutzer-ID, um sie an Ihre API zu senden. Sobald Sie dies haben, können Sie alle Informationen senden, die dieser eindeutigen Kennung zugeordnet sind.

Dadurch werden keine Cookies und keine lokale Speicherung mehr benötigt.


0

Ich kann nicht glauben, http://browserspy.dk wurde hier noch nicht erwähnt! Die Site beschreibt viele Funktionen (in Bezug auf die Mustererkennung), die zum Erstellen eines Klassifikators verwendet werden können.

Und natürlich würde ich zur Bewertung der Funktionen Support Vector Machines und insbesondere libsvm vorschlagen .


0

Verfolgen Sie sie während einer Sitzung oder über Sitzungen hinweg?

Wenn Ihre Site HTTPS Everywhere ist, können Sie die TLS-Sitzungs-ID verwenden, um die Sitzung des Benutzers zu verfolgen


1
Die Frage hier ist wie?
user455318

-2
  1. Erstellen Sie ein plattformübergreifendes Dummy-Plugin (nsapi) und generieren Sie einen eindeutigen Namen für den Namen oder die Version des Plugins, wenn der Benutzer es herunterlädt (z. B. nach der Anmeldung).
  2. Stellen Sie ein Installationsprogramm für das Plugin bereit / installieren Sie es gemäß den Richtlinien

Dies erfordert, dass der Benutzer die Kennung bereitwillig installiert.

Sobald das Plugin installiert ist, enthält der Fingerabdruck eines beliebigen (Plugin-fähigen) Browsers dieses spezielle Plugin. Um die Informationen an einen Server zurückzugeben, ist ein Algorithmus erforderlich, um das Plugin auf der Clientseite effektiv zu erkennen. Andernfalls benötigen Benutzer von IE und Firefox> = 28 eine Tabelle mit möglichen gültigen Identifikationen.

Dies erfordert eine relativ hohe Investition in eine Technologie, die wahrscheinlich von den Browser-Anbietern heruntergefahren wird. Wenn Sie Ihre Benutzer davon überzeugen können, ein Plugin zu installieren, gibt es möglicherweise auch Optionen wie die Installation eines lokalen Proxys , die Verwendung von VPN oder das Patchen der Netzwerktreiber.

Benutzer, die nicht identifiziert werden möchten (oder ihre Computer), werden immer einen Weg finden, dies zu verhindern.


Hallo, willkommen zum Stapelüberlauf. Bitte beachten Sie; this will require the user to willingly install the identifier.ist wahrscheinlich nicht das, was das Originalplakat (OP) bedeutete.
Stefan
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.