Розпізнавання користувачів без файлів cookie чи локального сховища


132

Я будую аналітичний інструмент, і в даний момент я можу отримати IP-адресу користувача, браузер та операційну систему від їх агента користувача.

Мені цікаво, чи є можливість виявити того самого користувача без використання файлів cookie чи локального сховища? Я не чекаю тут прикладів коду; лише простий натяк, куди шукати далі.

Забув згадати, що для цього ж комп’ютера / пристрою потрібно було б підтримувати крос-браузер. В основному я після розпізнавання пристрою насправді не користувач.


5
Насправді - принаймні, не так, щоб можна було покладатися на точність. Може бути хеш усіх трьох разом, але якщо більше одного будинку в будинку використовує один і той же браузер і ОС, він все одно не працює. Крім того, більшість провайдерів надають динамічні IP-адреси, тобто вони змінюються так часто і на них не можна покластися і для ідентифікації.
Джон

2
Тоді ви не знаєте, що таке сеанси. Ваш випадок використання - саме те, для чого були розроблені сесії. Сесії не мають нічого спільного з входом або автентифікацією. Ваш веб-сервер скаже клієнту надіслати файл cookie з ідентифікатором сеансу. Ви ідентифікуєте цього клієнта за допомогою ідентифікатора сеансу, який він вам надсилає.
Man Vs Code

4
Файли cookie ще працюватимуть Чому ви уникаєте використання файлів cookie?
Баба

2
Це дійсно просто, і я використовую його весь час, прошу користувача ввести ім’я користувача та пароль !!!
Аміт Криплані

2
Ось мінімальне рішення Javascript (не в цьому випадку крос-браузер): github.com/carlo/jquery-browser-fingerprint Я згадую про це, тому що це привело мене до думки, що багато плагінів встановлено крос-браузер за замовчуванням, без будь-який вибір з боку користувача. Упорядковано їх сортування (що не є невеликим завданням, але все ж ...) потенційно може призвести до відчутного властивості браузера для більшого відбитка пальця на основі пристрою.
hexalys

Відповіді:


389

Вступ

Якщо я вас правильно зрозумів, вам потрібно визначити користувача, для якого у вас немає унікального ідентифікатора, тому ви хочете з’ясувати, хто вони, шляхом зіставлення випадкових даних. Ви не можете надійно зберігати особу користувача, оскільки:

  • Файли cookie можна видалити
  • IP-адреса може змінюватися
  • Веб-переглядач може змінюватися
  • Кеш браузера може бути видалений

Яблучний аплет або Com Object було б простим рішенням, використовуючи хеш апаратної інформації, але в наші дні люди настільки обізнані в безпеці, що людям буде важко встановити подібні програми в їхній системі. Це не дасть вам застрягти з використанням файлів cookie та інших подібних інструментів.

Файли cookie та інші подібні інструменти

Ви можете розглянути можливість створення профілю даних та використання ймовірних тестів для ідентифікації ймовірного користувача . Корисний для цього профіль може бути сформований за допомогою комбінації з наступного:

  1. IP-адреса
    • Реальна IP-адреса
    • IP-адреса проксі (користувачі часто використовують один і той же проксі)
  2. Печиво
  3. Веб-помилки (менш надійні, оскільки помилки виправляються, але все ж корисні)
    • Файл PDF
    • Flash Bug
    • Java-помилка
  4. Браузери
    • Відстеження натискань (багато користувачів відвідують одну і ту ж серію сторінок під час кожного відвідування)
    • Відбиток пальців браузера - встановлені плагіни (люди часто мають різноманітні, дещо унікальні набори плагінів)
    • Кешовані зображення (люди іноді видаляють файли cookie, але залишають кешовані зображення)
    • Використання крапель
    • URL-адреси (історія веб-переглядача чи файли cookie можуть містити унікальні ідентифікатори користувача в URL-адресах, наприклад https://stackoverflow.com/users/1226894 або http://www.facebook.com/barackobama?fref=ts )
    • Виявлення системних шрифтів (це маловідома, але часто унікальна підпис ключа)
  5. HTML5 та Javascript
    • HTML5 LocalStorage
    • API геолокації HTML5 та зворотне геокодування
    • Архітектура, мова ОС, системний час, роздільна здатність екрана тощо.
    • API мережевої інформації
    • API стану акумулятора

Перераховані мною пункти - це, звичайно, лише декілька можливих способів, коли користувач може бути визначений однозначно. Є ще багато.

Що з цього набору елементів випадкових даних для побудови профілю даних, що далі?

Наступним кроком є ​​розробка якоїсь нечіткої логіки , а ще краще, штучної нейронної мережі (яка використовує нечітку логіку). У будь-якому випадку ідея полягає в тому, щоб навчити свою систему, а потім поєднати її навчання з байєсівським висновком, щоб підвищити точність результатів.

Штучна нейронна мережа

Бібліотека NeuralMesh для PHP дозволяє генерувати Штучні нейронні мережі. Для реалізації байєсівського висновку перегляньте такі посилання:

У цей момент ви можете думати:

Чому так багато математики та логіки для, здавалося б, простого завдання?

В основному, тому що це непросте завдання . Те, що ви намагаєтесь досягти, - це насправді Чиста ймовірність . Наприклад, з урахуванням таких відомих користувачів:

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

Коли ви отримуєте такі дані:

B + C + E + G + F + K

Питання, яке ви, по суті, задаєте:

Яка ймовірність того, що отримані дані (B + C + E + G + F + K) насправді є User1 або User2? І який із цих двох матчів найбільш вірогідний?

Щоб ефективно відповісти на це запитання, вам потрібно зрозуміти формат частоти проти ймовірності та чому спільна ймовірність може бути кращим підходом. Деталей занадто багато, щоб потрапити сюди (саме тому я даю вам посилання), але хорошим прикладом може бути додаток Майстра медичного діагностування , який використовує поєднання симптомів для виявлення можливих захворювань.

Подумайте на хвилину із серії точок даних, які містять Ваш профіль даних (B + C + E + G + F + K у прикладі вище) як симптоми , а невідомі користувачі - як захворювання . Визначивши захворювання, ви можете додатково визначити відповідне лікування (ставитися до цього користувача як до User1).

Очевидно, що хворобу, для якої ми виявили більше 1 симптому , легше визначити. Насправді, чим більше симптомів ми можемо виявити, тим легше і точніше наш діагноз майже певний.

Чи є інші альтернативи?

Звичайно. Як альтернативний захід, ви можете створити власний простий алгоритм оцінювання та базувати його на точних відповідностях. Це не настільки ефективно, як ймовірність, але може бути простішим у здійсненні.

Як приклад, розглянемо цю просту таблицю показників:

+ ------------------------- + -------- + ------------ +
| Майно | Вага | Важливість |
+ ------------------------- + -------- + ------------ +
| Реальна IP-адреса | 60 | 5 |
| Використовувана IP-адреса проксі | 40 | 4 |
| HTTP cookies | 80 | 8 |
| Сесійні файли cookie | 80 | 6 |
| Файли cookie сторонніх | 60 | 4 |
| Flash Cookies | 90 | 7 |
| PDF-помилка | 20 | 1 |
| Flash Bug | 20 | 1 |
| Java Bug | 20 | 1 |
| Часті сторінки | 40 | 1 |
| Відбитки пальців браузера | 35 | 2 |
| Встановлені плагіни | 25 | 1 |
| Кешовані зображення | 40 | 3 |
| URL | 60 | 4 |
| Виявлення системних шрифтів | 70 | 4 |
| Місцеве зберігання | 90 | 8 |
| Геолокація | 70 | 6 |
| АОЛТР | 70 | 4 |
| API інформації про мережу | 40 | 3 |
| API стану акумулятора | 20 | 1 |
+ ------------------------- + -------- + ------------ +

За кожну інформацію, яку ви можете зібрати за певним запитом, присвойте відповідний бал, а потім використовуйте Важливість для вирішення конфліктів, коли бали однакові.

Доказ концепції

Для простого доказу концепції, будь ласка, подивіться на Perceptron . Perceptron - це модель РНК, яка зазвичай використовується у програмах розпізнавання образів. Існує навіть старий клас PHP, який ідеально реалізує його, але вам, ймовірно, доведеться змінити його для своїх цілей.

Незважаючи на те, що він є чудовим інструментом, Perceptron може все-таки повернути декілька результатів (можливих матчів), тому використання порівняння «Оцінка та Різниця» все ще корисно для визначення найкращого з цих матчів.

Припущення

  • Зберігати всю можливу інформацію про кожного користувача (IP, файли cookie тощо)
  • Якщо результат відповідає точній відповідності, збільште бал на 1
  • Якщо результат не відповідає точності, зменшіть бал на 1

Очікування

  1. Створюйте мітки РНК
  2. Створення випадкових користувачів, що емулюють базу даних
  3. Створити одного невідомого користувача
  4. Створення РНК та цінностей невідомого користувача
  5. Система об'єднає інформацію РНК і навчить Перцептрону
  6. Після тренування Perceptron система матиме набір зважувань
  7. Тепер ви можете протестувати шаблон Невідомого користувача, і Perceptron створить набір результатів.
  8. Зберігайте всі позитивні сірники
  9. Сортуйте збіги спочатку за Оцінками, потім за різницею (як описано вище)
  10. Виведіть два найближчих збіги або, якщо не знайдено відповідностей, виведіть порожні результати

Код для підтвердження концепції

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

Вихід:

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

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

Якщо Debug = true, ви зможете побачити вхідні дані (датчик та бажані), початкові ваги, вихідний сигнал (датчик, сума, мережа), помилка, корекція та кінцеві ваги .

+----+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+-----+----+---------+---------+---------+---------+---------+---------+---------+---------+---------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----------+
| 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 до x20 представляють функції, перетворені кодом.

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

Ось онлайн демонстрація

Клас:

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

Модифікований клас рецепторів

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

Висновок

Ідентифікація користувача без унікального ідентифікатора - це не пряма задача чи проста задача. це залежить від збору достатньої кількості випадкових даних, які ви можете зібрати у користувача різними методами.

Навіть якщо ви вирішите не використовувати Штучну нейронну мережу, я пропоную хоча б використовувати Просту матрицю ймовірностей з пріоритетами та ймовірностями - і сподіваюся, що наведений вище код та приклади дають вам достатньо для продовження.


@ Baba Що ви розумієте під використанням "Blobs" для відбитків браузера?
billmalarky


1
@Baba Як би це можна було використовувати для відбитків браузера? Просто перевірте, що зараз у ній є у будь-який момент?
billmalarky

@ Baba велика робота, я завжди намагався мати якусь багаторівневу стратегію для ідентифікації користувача, але, як ви сказали, кеш можна очистити, змінити IP-адреси, користувачів за допомогою проксі-серверів або NAT - особливо тих людей -, видалити файли cookie тощо. Але навіть при всьому цьому багато зусиль, це ймовірність питання, також якщо поганий користувач, наприклад, використовує браузер Tor , більшість, якщо не всі згадані стратегії виявлення не спрацюють. Мені сподобалось browserleaks.com, але з Tor все повернулося невизначеним або невідомим
Mi-Creative

Лише Примітка, призначена лише для "видалення пилу" з цієї дорогоцінної камери публікації: Список зламаних посилань станом на 07.09.17: - Implement Bayesian inference using PHP, всі 3 частини. - Frequency vs Probability - Joint Probability -Input (Sensor & Desired), Initial Weights, Output (Sensor, Sum, Network), Error, Correction and Final Weights
Ziezi

28

Ця методика (для виявлення тих самих користувачів без файлів cookie - або навіть без ip адреси) називається відбитком пальця браузера . В основному ви скануєте як інформацію про браузер, наскільки це можливо - кращі результати можна досягти за допомогою JavaScript, flash або java (f.ex. встановлені розширення, шрифти тощо). Після цього, якщо ви хочете, ви можете зберігати хешовані результати.

Це не непогрішно, але:

83,6% бачених браузерів мали унікальний відбиток пальців; серед тих, хто підтримує Flash або Java, 94,2%. Це не включає файли cookie!

Більше інформації:


я думаю, це все ще відповідь. якщо вам потрібно ідентифікувати пристрій, вам потрібно отримати лише ці дані - f.ex. ОС, загальні розширення (та його 'версії), встановлені шрифти тощо ...
pozs

Це не спрацює добре. Кожен браузер підтримує сеанси та файли cookie. Використовуйте правильний інструмент для роботи.
Man Vs Code

1
@ slash197 що з кеш-файлом? я маю на увазі використання прозорого флеш-носія 1px x 1px разом із файлом xml, який містить унікальний згенерований ідентифікатор всередині (xml слід створити один раз на сервері, перш ніж його завантажувати на локальний HD користувача) таким чином, навіть якщо користувач видаляє файли cookie або вихід, ви все ще можете мати міст, використовуючи метод сценарію дії sendAndLoad.
Мбаррі

Мінімум змін вплине на хеш-результат. наприклад версія плеєра ударної хвилі. можливе рішення з локально збереженим файлом кеша xml з унікальним ключем + прихованим 1px x 1px флеш-носієм (сценарій дії) у браузері, таким чином ви позбудетеся від cookie-файлів, питання про закінчення сеансу, якщо це було основною проблемою. ви все ще можете мати міст між вашою базою даних sql та ключем на локальній машині користувача.
Мбаррі

@Mbarry Я не дуже шанувальник флеш-пам’яті, але якщо в браузері є надбудова, що блокує спалах, як у мене, що носій Flash1 Flash пікселів буде вимкнено, чи не так?
slash197

7

Вищезазначене відбиття пальців працює, але все ж може зазнати колізій.

Один із способів - додати UID до URL кожної взаємодії з користувачем.

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

Де кожна посилання на сайті адаптована до цього модифікатора. Це аналогічно тому, як ASP.Net використовував роботу з використанням FORM-даних між сторінками.


Я подумав про це, але це найпростіший спосіб для користувача змінити його
slash197

1
не ідентифікатор - це хеш, що сам посилається. Робить це криптографічно захищеним.
Джастін Олександр

Крім того, цей спосіб нормальний, коли хтось переглядає сайт, але як ви пропонуєте розглянути той випадок, коли користувач, що повертається, повертається через тиждень і просто набирає адресу веб-сайтів, без ідентифікатора?
slash197

@ slash197 у такому випадку, чому ви не скажете користувачеві ввійти, що відбувається, навіть якщо користувач видаляє файли cookie.
Акаш Кава

6

Ви заглянули в Evercookie ? Він може працювати або не працювати у веб-переглядачах. Виписка з їх сайту.

"Якщо користувач отримує файли cookie в одному веб-переглядачі і переходить на інший браузер, якщо у них все ще є файл" Local Shared Object ", файл cookie відтворюватиметься в обох браузерах."


Цікаво, чи працює він з відключеним JavaScript. Чи маєте ви досвід?
Войтек

Це називається evercookie з причини, воно працюватиме незважаючи ні на що. Їм видалити файли cookie майже неможливо.
Алексіс Тайлер

Незважаючи ні на що, це не вийде. З першого рядка опису: "evercookie - це JavaScript JavaScript ...". Він не працюватиме, якщо JavaScript відключений.
gdw2

Не повинно бути навіть js вимкнено. Ghostery і uBlock краплі evercookie
opengrid

3

Ви можете зробити це за допомогою кешованого png, це було б дещо ненадійно (різні браузери поводяться по-різному, і вийде з ладу, якщо користувач очистить кеш-пам'ять), але це варіант.

1: встановити Базу даних, яка зберігає унікальний ідентифікатор користувача у вигляді шістнадцяткових рядків

2: створити файл genUser.php (або будь-якої мови), який генерує ідентифікатор користувача, зберігає його в БД, а потім створює справжній колір .png зі значень цієї шістнадцяткової рядки (кожен піксель буде 4 байти) і повертає що для браузера. Не забудьте встановити тип вмісту та заголовки кешу.

3: у HTML або JS створіть подібне зображення <img id='user_id' src='genUser.php' />

4: намалюйте це зображення на полотні ctx.drawImage(document.getElementById('user_id'), 0, 0);

5: читайте байти цього зображення за допомогою ctx.getImageDataта перетворюйте цілі числа в шістнадцятковий рядок.

6: Це ваш унікальний ідентифікатор користувача, який зараз кешується на вашому комп'ютері користувачів.


Він хоче щось, що може відслідковувати користувача "через браузери", який тут не працюватиме (кожен браузер має власну базу даних кешу).
EricLaw

Де ви це бачите, його питання запитує лише "Забув згадати, що це потрібно бути сумісним між браузером", тобто працювати в будь-якому браузері.
hobberwickey

Його питання погано написане. I'm after device recognitionцю пропозицію для того, що він хоче, і він докладно тут: stackoverflow.com/questions/15966812 / ...
EricLaw

2

Виходячи з сказаного:

В основному я після розпізнавання пристрою насправді не користувач

Найкращий спосіб зробити це - надіслати mac-адресу, яка є ідентифікатором NIC.

Ви можете подивитися на цю публікацію: Як я можу отримати MAC та IP-адресу підключеного клієнта в PHP?


Вибачте, але ідентифікатор NIC легко піддається підробці. Це, безумовно, не найкращий спосіб.
асгс

Відбитка пальців у веб-переглядачі @asgs, можливо, буде кращою, чи що, на вашу думку, буде найкращим?
Мехді Карамослі

Не існує найкращого способу, це сумна частина цього. Однак, це та браузерний FingerPrinting у поєднанні з дослідженням ймовірностей, яке Баба представила вище, було б найкращим на мою думку.
asgs

1

Ви можете це зробити з етагами. Хоча я не впевнений, чи було подано цю юридичну як купу позовів.

Якщо ви належним чином попереджаєте своїх користувачів або у вас є щось на зразок веб-сайту інтранет, це може бути нормально.


Позначки не сумісні між веб-переглядачами.
slash197

1
Етикети є частиною специфікації HTTP / 1.1. Усі популярні веб-переглядачі підтримують етаги, вам би знадобилося написати власний веб-переглядач, щоб не підтримувати заголовки ETag / If-None-Match.
Брайан Макгініті

Я не казав, що це не підтримує, я сказав, що це не перехресно браузер. Якщо тег збережено у Firefox, він недоступний у chrome, тому вміст буде завантажено знову, оскільки немає кешу.
slash197

Тепер я розумію, що ви говорили. Ти маєш рацію. У кожного браузера є власний магазин кешу, отже, різні етаги.
Брайан Макгініті

1

Ви потенційно можете створити крапку для зберігання ідентифікатора пристрою ...

Недоліком є ​​те, що користувачеві потрібно завантажити блок ( ви можете змусити його завантажити ), оскільки браузер не може отримати доступ до Файлової системи, щоб безпосередньо зберегти файл.

довідка:

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


0

Неефективним, але, можливо, дасть бажані результати, було б опитування API на вашому боці. Проводити фоновий процес на стороні клієнта, який надсилає дані користувача з інтервалом. Вам знадобиться ідентифікатор користувача для надсилання у ваш API. Після цього ви зможете надсилати будь-яку інформацію, пов’язану з цим унікальним ідентифікатором.

Це знімає потребу в печиві та локальному зберіганні.


0

Я не можу повірити, http://browserspy.dk досі тут не згадувались! На сайті описано безліч функцій (з точки зору розпізнавання шаблонів), які можна використовувати для побудови класифікатора.

І для того, щоб оцінити особливості, я б запропонував підтримати векторні машини та libsvm зокрема.


0

Відстежувати їх під час сеансу чи протягом сеансів?

Якщо на вашому веб-сайті є HTTPS скрізь, ви можете використовувати ідентифікатор сесії TLS для відстеження сеансу користувача


1
питання тут як?
користувач455318

-2
  1. створити плагін крос-платформи (nsapi) і створити унікальне ім’я для імені або версії плагіна, коли користувач завантажує його (наприклад, після входу в систему).
  2. надайте інсталятор плагіна / встановити його відповідно до політики

це вимагає від користувача охочого встановлення ідентифікатора.

як тільки плагін встановлений, відбиток пальця будь-якого (увімкнено плагін) буде містити саме цей плагін. Для повернення інформації на сервер необхідний алгоритм для ефективного виявлення плагіна на стороні клієнта, інакше для IE і Firefox> = 28 користувачів знадобиться таблиця можливих дійсних ідентифікаторів.

Це вимагає відносно великих інвестицій у технологію, яка, ймовірно, буде закрита постачальниками браузерів. Коли ви зможете переконати своїх користувачів встановити плагін, також можуть бути такі варіанти, як встановити локальний проксі , використовувати vpn або виправити мережеві драйвери.

Користувачі, які не хочуть ідентифікувати (або їх машини), завжди знайдуть спосіб запобігти цьому.


Привіт, ласкаво просимо, щоб стек перелив. Будь ласка, запиши; this will require the user to willingly install the identifier.це, мабуть, не те, що мав на увазі оригінальний плакат.
Стефан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.