Rozpoznawanie użytkownika bez plików cookie lub lokalnego przechowywania

Buduję narzędzie analityczne i obecnie mogę pobrać adres IP użytkownika, przeglądarkę i system operacyjny z ich agenta użytkownika.

Zastanawiam się, czy jest możliwość wykrycia tego samego Użytkownika bez używania plików cookie lub lokalnego przechowywania? Nie spodziewam się tutaj przykładów kodu; tylko prosta podpowiedź, gdzie szukać dalej.

Zapomniałem wspomnieć, że musi być kompatybilny z przeglądarką, jeśli jest to ten sam komputer / urządzenie. Zasadniczo jestem po rozpoznaniu urządzenia nie bardzo użytkownika.

Author: Konrad Borowski, 2013-04-12

12 answers

Wprowadzenie

Jeśli dobrze cię rozumiem, musisz zidentyfikować użytkownika, dla którego nie masz unikalnego identyfikatora, więc chcesz dowiedzieć się, kim są, dopasowując losowe DANE. Nie można wiarygodnie przechowywać tożsamości użytkownika, ponieważ:

  • Pliki cookie można usunąć
  • adres IP może ulec zmianie
  • Przeglądarka Może Się Zmienić
  • Pamięć podręczna przeglądarki może zostać usunięta

Aplet Javy lub obiekt Com byłby łatwym rozwiązaniem używając hasha informacji o sprzęcie, ale w dzisiejszych czasach ludzie są tak świadomi bezpieczeństwa, że trudno byłoby nakłonić ludzi do zainstalowania tego rodzaju programów w swoim systemie. Oznacza to, że nie musisz używać plików cookie i innych podobnych narzędzi.

Pliki cookie i inne podobne narzędzia

Możesz rozważyć zbudowanie Profilu danych, a następnie użyć testów prawdopodobieństwa, aby zidentyfikować prawdopodobnego użytkownika. Profil przydatny do tego może być generowany przez pewną kombinację po:
  1. adres IP
    • prawdziwy adres IP
    • Adres IP serwera Proxy (użytkownicy często używają tego samego serwera proxy wielokrotnie)]}
  2. ciasteczka
  3. błędy sieciowe (mniej wiarygodne, ponieważ błędy są naprawiane, ale nadal przydatne)
    • błąd PDF
    • Flash Bug
    • Błąd Javy
  4. przeglądarki
      Śledzenie kliknięć (wielu użytkowników odwiedza tę samą serię stron przy każdej wizycie)]}
    • Browsers Finger Print   - Zainstalowane wtyczki (ludzie często mają różne, nieco unikalne zestawy wtyczek)
    • buforowane obrazy (ludzie czasami usuwają swoje pliki cookie, ale zostawiają buforowane obrazy)
    • Używanie Blobów
    • URL (historia przeglądarki lub pliki cookie mogą zawierać unikalne identyfikatory użytkowników w adresach URL, takie jak https://stackoverflow.com/users/1226894 lub http://www.facebook.com/barackobama?fref=ts )
    • wykrywanie czcionek systemowych (jest to mało znany, ale często unikalny podpis klucza)
  5. HTML5 & Javascript
  6. Architektura, język systemu operacyjnego, czas systemowy, rozdzielczość ekranu itp.
  7. Network Information API
  8. Bateria Status API

Pozycje, które wymieniłem, to oczywiście tylko kilka możliwych sposobów na unikalną identyfikację użytkownika. Jest ich o wiele więcej.

Co dalej z tym zestawem losowych elementów danych, z których można zbudować profil danych?

Następnym krokiem jest opracowanie logiki rozmytej , lub, jeszcze lepiej, sztucznej sieci neuronowej (która wykorzystuje logikę rozmytą). W obu przypadkach chodzi o to, aby trenować swój system, a następnie połączyć jego trening z wnioskowaniem Bayesowskim W celu zwiększenia dokładności wyników.

Sztuczna Sieć Neuronowa

Biblioteka NeuralMesh dla PHP pozwala na generowanie sztucznych sieci neuronowych. Aby zaimplementować wnioskowanie bayesowskie, sprawdź następujące linki:

W tym momencie możesz myśleć:

Po co tyle matematyki i logiki na pozornie proste zadanie?

Zasadniczo, ponieważ jest to nie jest to proste zadanie . To, co próbujesz osiągnąć, to w rzeczywistości czyste prawdopodobieństwo . Na przykład, biorąc pod uwagę następujących znanych użytkowników:

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

Gdy otrzymasz następujące dane:

B + C + E + G + F + K

Pytanie, które w zasadzie zadajesz, brzmi:

Jakie jest prawdopodobieństwo że odebrane dane (B + C + E + G + F + K) to faktycznie User1 czy User2? A który z tych dwóch meczów jest najbardziej prawdopodobny?

Aby skutecznie odpowiedzieć na to pytanie, musisz zrozumieć Częstotliwość vs Format prawdopodobieństwa i dlaczego wspólne prawdopodobieństwo może być lepszym podejściem. Szczegóły są zbyt wiele, aby dostać się tutaj (dlatego podaję linki), ale dobrym przykładem może być Medical Diagnosis Wizard Application, który wykorzystuje kombinację objawów w celu identyfikacji możliwych chorób.

Pomyśl przez chwilę o serii punktów danych, które składają się na Twój profil danych (B + C + E + G + F + K w powyższym przykładzie) jako objawy , A nieznani użytkownicy jako choroby. Identyfikując chorobę, możesz dalej zidentyfikować odpowiednie leczenie (traktuj tego użytkownika jako User1).

Oczywiście, choroba dla której zidentyfikowaliśmy więcej niż 1 objaw jest łatwiejszy do zidentyfikuj się. W rzeczywistości, im więcej objawów możemy zidentyfikować, tym łatwiejsza i dokładniejsza nasza diagnoza jest prawie pewna.

Czy są jakieś inne alternatywy?

Oczywiście. Alternatywną miarą może być stworzenie własnego prostego algorytmu punktacji i oparcie go na dokładnych meczach. Nie jest to tak skuteczne, jak Prawdopodobieństwo, ale może być prostsze do wdrożenia.

Jako przykład rozważ ten prosty wykres punktowy:

+-------------------------+--------+------------+
|        Property         | Weight | Importance |
+-------------------------+--------+------------+
| Real IP address         |     60 |          5 |
| Used proxy IP address   |     40 |          4 |
| HTTP Cookies            |     80 |          8 |
| Session Cookies         |     80 |          6 |
| 3rd Party Cookies       |     60 |          4 |
| Flash Cookies           |     90 |          7 |
| PDF Bug                 |     20 |          1 |
| Flash Bug               |     20 |          1 |
| Java Bug                |     20 |          1 |
| Frequent Pages          |     40 |          1 |
| Browsers Finger Print   |     35 |          2 |
| Installed Plugins       |     25 |          1 |
| Cached Images           |     40 |          3 |
| URL                     |     60 |          4 |
| System Fonts Detection  |     70 |          4 |
| Localstorage            |     90 |          8 |
| Geolocation             |     70 |          6 |
| AOLTR                   |     70 |          4 |
| Network Information API |     40 |          3 |
| Battery Status API      |     20 |          1 |
+-------------------------+--------+------------+

Dla każdego informacje, które możesz zebrać na dane żądanie, przyznać powiązany wynik, a następnie użyć ważności do rozwiązywania konfliktów, gdy wyniki są takie same.

Proof of Concept

Aby uzyskać prosty dowód koncepcji, proszę spojrzeć na Perceptron . Perceptron jest modelem RNA, który jest powszechnie stosowany w aplikacjach rozpoznawania wzorców. Istnieje nawet stara Klasa PHP, która implementuje ją doskonale, ale prawdopodobnie musisz zmodyfikować go do swoich celów.

Pomimo tego, że Perceptron jest świetnym narzędziem, nadal może zwracać wiele wyników (możliwych meczów), więc korzystanie z porównania wyników i różnic jest nadal przydatne do identyfikacji najlepszych z tych meczów.

Założenia

  • przechowywać wszystkie możliwe informacje o każdym użytkowniku (IP, cookies, itp.)
  • jeśli wynik jest dokładnie dopasowany, zwiększ wynik o 1
  • gdzie wynik nie jest dokładnym dopasowaniem, spadek ocena przez 1

Oczekiwanie

  1. generowanie etykiet RNA
  2. generowanie losowych użytkowników emulujących bazę danych
  3. Wygeneruj jednego nieznanego użytkownika
  4. generowanie nieznanego użytkownika RNA i wartości
  5. System połączy informacje o RNA i nauczy Perceptron.]} Po treningu Perceptron system będzie miał zestaw ważeń [18]}
  6. możesz teraz przetestować wzór nieznanego użytkownika, a Perceptron da wynik gotowi.
  7. Przechowuj wszystkie pozytywne dopasowania
  8. Sortuj mecze najpierw według wyniku, a następnie według różnicy (jak opisano powyżej)
  9. wyświetla dwa najbliższe dopasowania lub, jeśli nie znaleziono dopasowań, wyświetla puste wyniki

Kod dowodu koncepcji

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

Wyjście:

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

Print_r z "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
)

If debug = true you would be able to see Input (Sensor & Desired), Initial wag, Output (Sensor, Sum, Network), błąd, korekta i waga końcowa .

+----+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+-----+----+---------+---------+---------+---------+---------+---------+---------+---------+---------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----------+
| 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 do x20 reprezentują funkcje konwertowane przez kod.

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

Oto demo online

Klasa Użyta:

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

Zmodyfikowana Klasa Perceptron

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

Wniosek

Identyfikacja użytkownika bez unikalnego identyfikatora nie jest prostym ani prostym zadaniem. jest to uzależnione od zebrania odpowiedniej ilości losowych danych które są w stanie zebrać od Użytkownika za pomocą różnych metod.

Nawet jeśli zdecydujesz się nie używać sztucznej sieci neuronowej, sugeruję przynajmniej użycie prostej macierzy prawdopodobieństwa z priorytetami i możliwościami-i mam nadzieję, że powyższy kod i przykłady dadzą ci wystarczająco dużo, aby kontynuować.

 367
Author: Baba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:07

Ta technika (do wykrywania tych samych użytkowników bez plików cookie - lub nawet bez adresu ip) nazywa się browser fingerprinting . Zasadniczo pełzasz jako informacje o przeglądarce, jak możesz-lepsze wyniki można osiągnąć za pomocą javascript, flash lub java (np. zainstalowane rozszerzenia, czcionki itp.). Następnie możesz przechowywać wyniki zahaszowane, jeśli chcesz.

Nie jest nieomylny, ale:

83,6% przeglądarek miało unikalny odcisk palca; wśród tych z Flashem lub Java enabled, 94.2%. Nie obejmuje to Plików cookie!

Więcej informacji:

 27
Author: pozs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-18 20:43:00

Wyżej wymieniony odcisk kciuka działa, ale nadal może cierpieć na kolizje.

Jednym ze sposobów jest dodanie UID do adresu url każdej interakcji z użytkownikiem.

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

Gdzie każdy link w witrynie jest dostosowywany tym modyfikatorem. Jest to podobne do sposobu ASP.Net służy do pracy z danymi formularza między stronami.

 5
Author: Justin Alexander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-21 11:18:28

Zajrzałeś do Evercookie ? Może, ale nie musi, działać w różnych przeglądarkach. Wyciąg z ich strony.

" jeśli użytkownik zostanie gotowany w jednej przeglądarce i przełączy się na inną przeglądarkę, tak długo, jak nadal mają lokalny plik cookie Shared Object, plik cookie będzie odtwarzane w obu przeglądarkach."

 5
Author: Alexis Tyler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-23 14:30:14

Można to zrobić z buforowanym png, byłoby to nieco zawodne (różne przeglądarki zachowują się inaczej i zawiedzie, jeśli użytkownik wyczyści pamięć podręczną), ale jest to opcja.

1: Skonfiguruj bazę danych, która przechowuje unikalny identyfikator użytkownika jako ciąg szesnastkowy

2: Utwórz genUser.plik php (lub jakikolwiek inny język), który generuje identyfikator użytkownika, przechowuje go w DB, a następnie tworzy prawdziwy kolor .png z wartości tego ciągu szesnastkowego (każdy piksel będzie miał 4 bajty) i zwróci go do przeglądarka. Pamiętaj, aby ustawić nagłówki content-type I Cache.

3: w HTML lub JS Utwórz obrazek w stylu <img id='user_id' src='genUser.php' />

4: narysuj Ten obraz na płótnie ctx.drawImage(document.getElementById('user_id'), 0, 0);

5: odczytaj bajty tego obrazu za pomocą ctx.getImageData i przekonwertuj liczby całkowite na ciąg szesnastkowy.

6: to jest Twój unikalny identyfikator użytkownika, który jest teraz buforowany na komputerze użytkowników.

 2
Author: hobberwickey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-23 13:46:49

Na podstawie tego, co powiedziałeś:

W zasadzie chodzi mi o rozpoznawanie urządzeń, a nie o Użytkownika

Najlepszym sposobem jest wysłanie adresu mac, który jest identyfikatorem NIC.

Możesz rzucić okiem na ten post : Jak mogę uzyskać MAC i adres IP podłączonego klienta w PHP?

JavaScript Mac Finder

 2
Author: Mehdi Karamosly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:09

Możesz to zrobić za pomocą etags. Chociaż nie jestem pewien, czy to legalne jako kilka pozwów zostały złożone.

Jeśli odpowiednio ostrzec użytkowników lub jeśli masz coś w rodzaju strony intranetowej może być ok.

 1
Author: Brian McGinity,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-21 13:21:04

Potencjalnie można utworzyć obiekt blob do przechowywania identyfikatora urządzenia ...

Minusem jest to, że użytkownik musi pobrać blob ( możesz wymusić pobieranie ), ponieważ przeglądarka nie może uzyskać dostępu do systemu plików, aby bezpośrednio zapisać plik.

Odniesienie:

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

 1
Author: DanielDMO,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-23 18:49:05

Nieefektywne, ale może dać pożądane rezultaty, byłoby ankieta API po twojej stronie. Mieć proces w tle po stronie klienta, który wysyła dane użytkownika w interwale. Do wysłania do API potrzebny będzie identyfikator użytkownika. Gdy już to posiadasz, możesz przesłać wszystkie informacje związane z tym unikalnym identyfikatorem.

Eliminuje to potrzebę stosowania plików cookie i localstorage.

 0
Author: rexposadas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-22 19:39:08

I can ' t believe, http://browserspy.dk nadal nie został wymieniony tutaj! Strona opisuje wiele funkcji (w zakresie rozpoznawania wzorców), które można wykorzystać do zbudowania klasyfikatora.

I przyczyny, dla oceny cech sugerowałbym Maszyny wektorowe wsparcia i libsvm w szczególności.

 0
Author: Valentin Heinitz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-20 13:42:32

Śledzić je podczas sesji lub w trakcie sesji?

Jeśli Twoja witryna jest HTTPS wszędzie, możesz użyć identyfikatora sesji TLS do śledzenia sesji użytkownika

 0
Author: Neil McGuigan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-07 03:23:58
  1. Utwórz wtyczkę cross-platform dummy (nsapi) i wygeneruj unikalną nazwę dla nazwy wtyczki lub wersji, gdy użytkownik ją pobierze (np. po zalogowaniu).
  2. podaj instalator dla wtyczki / zainstaluj go zgodnie z Polityką

Będzie to wymagało od użytkownika dobrowolnej instalacji identyfikatora.

Po zainstalowaniu wtyczki, fingerprint dowolnej przeglądarki (włączonej przez wtyczkę) będzie zawierał tę konkretną wtyczkę. Aby zwrócić informacje na serwer, algorytm do skuteczne wykrywanie wtyczki po stronie klienta jest potrzebne, w przeciwnym razie IE i Firefox > = 28 użytkownicy będą potrzebować tabeli możliwych ważnych identyfikatorów.

Wymaga to stosunkowo wysokich inwestycji w technologię, która prawdopodobnie zostanie wyłączona przez dostawców przeglądarek. Kiedy jesteś w stanie przekonać użytkowników do zainstalowania wtyczki, mogą być również opcje takie jak zainstaluj lokalny serwer proxy, użyj vpn lub załataj sterowniki sieciowe.

Użytkownicy, którzy nie chcą być identyfikowani (lub ich Maszyny) zawsze znajdzie sposób, aby temu zapobiec.

 -2
Author: aec8adaikaeNg6hey2oof8otai9quo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-24 23:19:10