Intereting Posts
Предупреждение: PDOStatement :: execute (): SQLSTATE : Недопустимый номер параметра: количество связанных переменных не совпадает с числом токенов в Проблемы с безопасным связыванием с Active Directory с помощью PHP Ошибка анализа: синтаксическая ошибка: неожиданный '{' Как проверить, соответствует ли текущая дата / время заданной дате / времени? Несколько экземпляров (2) Zend_Auth json_decode для пользовательского класса Создание динамической таблицы с использованием php на основе входных данных пользователей Любой способ вернуть PHP `json_encode` с кодировкой UTF-8, а не Unicode? Мне нужна моя страница PHP, чтобы показать мой образ BLOB из базы данных mysql Могу ли я установить Laravel без использования Composer? Как использовать PHP cURL для отправки изображений с правильным типом контента? PHP API для Hotmail, Gmail и Yahoo? SQL-запрос, выберите ближайшие места по заданным координатам Как отправить форму с помощью AJAX / JSON? PHP gettext в Windows

Пользовательское распознавание без файлов cookie или локального хранилища

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

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

Забыл упомянуть, что он должен быть совместим с несколькими браузерами, если это тот же компьютер / устройство. В принципе, я не признаю распознавание устройства.

Solutions Collecting From Web of "Пользовательское распознавание без файлов cookie или локального хранилища"

Введение

Если вы правильно поняли, вам нужно определить пользователя, для которого у вас нет уникального идентификатора, поэтому вы хотите выяснить, кто они, сопоставляя случайные данные. Вы не можете надежно хранить идентификатор пользователя, потому что:

  • Файлы cookie могут быть удалены
  • IP-адрес Может меняться
  • Браузер может измениться
  • Кэш-браузер можно удалить

Апплет Java или Com Object был бы простым решением с использованием хеш-информации об оборудовании, но в наши дни люди настолько осведомлены о безопасности, что было бы сложно заставить людей устанавливать эти программы в своей системе. Это оставляет вас застрявшим с использованием Cookies и других подобных инструментов.

Печенье и другие подобные инструменты

Вы можете подумать о создании профиля данных, а затем использовать тесты вероятности для определения Вероятного пользователя . Профиль, полезный для этого, может быть сгенерирован некоторой комбинацией следующего:

  1. Айпи адрес
    • Реальный IP-адрес
    • IP-адрес прокси (пользователи часто используют один и тот же прокси-сервер)
  2. Печенье
    • HTTP Cookies
    • Сессионные Cookies
    • Сторонние файлы cookie
    • Flash Cookies ( большинство людей не знают, как их удалить )
  3. Веб-ошибки (менее надежны, потому что ошибки исправляются, но все же полезны)
    • Ошибка PDF
    • Ошибка Flash
    • Ошибка Java
  4. Браузеры
    • Нажмите «Отслеживание» (многие пользователи посещают ту же серию страниц при каждом посещении)
    • Браузеры Finger Print – Установленные плагины (люди часто имеют разные, несколько уникальные наборы плагинов)
    • Кэшированные изображения (люди иногда удаляют свои файлы cookie, но оставляют кешированные изображения)
    • Использование Blobs
    • 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 позволяет создавать искусственные нейронные сети. Чтобы реализовать байесовский вывод, ознакомьтесь со следующими ссылками:

  • Реализовать байесовский вывод с использованием PHP, часть 1
  • Реализовать байесовский вывод с использованием PHP, часть 2
  • Реализовать байесовский вывод с использованием PHP, часть 3

На данный момент вы можете подумать:

Почему так много математики и логики для кажущейся простой задачи?

В принципе, потому что это непростая задача . То, что вы пытаетесь достичь, – это, по сути, Чистая Вероятность . Например, с учетом следующих известных пользователей:

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 |
 |  Кулинарные рецепты |  60 |  4 |
 |  Flash Cookies |  90 |  7 |
 |  Ошибка PDF |  20 |  1 |
 |  Ошибка Flash |  20 |  1 |
 |  Ошибка Java |  20 |  1 |
 |  Частые страницы |  40 |  1 |
 |  Браузеры Finger Print |  35 |  2 |
 |  Установленные плагины |  25 |  1 |
 |  Кэшированные изображения |  40 |  3 |
 |  URL |  60 |  4 |
 |  Обнаружение системных шрифтов |  70 |  4 |
 |  Localstorage |  90 |  8 |
 |  Геолокация |  70 |  6 |
 |  AOLTR |  70 |  4 |
 |  Сетевой информационный API |  40 |  3 |
 |  Батарея Статус API |  20 |  1 |
 + ------------------------- + -------- + ------------ +

Для каждой части информации, которую вы можете собрать по заданному запросу, присудите соответствующий балл, затем используйте значение «Важность» для разрешения конфликтов, если баллы одинаковы.

Доказательство концепции

Для простого доказательства концепции, пожалуйста, взгляните на Перцептрона . Перцептрон – это модель РНК, которая обычно используется в приложениях распознавания образов. Существует даже старый PHP-класс, который прекрасно его реализует, но вам, скорее всего, придется его модифицировать для своих целей.

Несмотря на то что это отличный инструмент, Perceptron все еще может возвращать несколько результатов (возможные совпадения), поэтому использование сравнения по шкале и разнице по-прежнему полезно для определения наилучшего из этих совпадений.

Предположения

  • Храните всю возможную информацию о каждом пользователе (IP, файлы cookie и т. Д.).
  • Где результат – точное совпадение, увеличьте счет на 1
  • Если результат не является точным, уменьшите оценку на 1

ожидание

  1. Создание меток РНК
  2. Создание случайных пользователей, имитирующих базу данных
  3. Создание единого Неизвестного пользователя
  4. Генерировать неизвестную пользовательскую РНК и значения
  5. Система объединит информацию РНК и научит Perceptron
  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, вы сможете увидеть Input (Sensor & Desired), Initial Weight, Output (Sensor, Sum, Network), Error, Correction и Final Weights .

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

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 

Вывод

Идентификация пользователя без уникального идентификатора не является прямой или простой задачей. это зависит от сбора достаточного количества случайных данных, которые вы можете собирать у пользователя различными способами.

Даже если вы решите не использовать искусственную нейронную сеть, я предлагаю по крайней мере использовать простую матрицу вероятностей с приоритетами и вероятностями – и я надеюсь, что приведенный выше код и примеры дают вам достаточно возможностей для продолжения.

Этот метод (для обнаружения тех же пользователей без куки-файлов или даже без ip-адреса) называется отпечатком пальца браузера . В основном вы сканируете как информацию о браузере, как можете – лучшие результаты могут быть достигнуты с помощью javascript, flash или java (f.ex. установлены расширения, шрифты и т. Д.). После этого вы можете сохранить результаты хэширования, если хотите.

Это не непогрешимо, но:

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

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

Вышеупомянутые операции с печатью, но могут по-прежнему страдать от коллизий.

Один из способов – добавить UID к URL-адресу каждого взаимодействия с пользователем.

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

Где каждая ссылка на сайте адаптируется с этим модификатором. Это похоже на способ использования ASP.Net с использованием данных FORM между страницами.

Вы заглянули в Evercookie ? Он может работать или не работать в браузерах. Экстракт со своего сайта.

«Если пользователь получает cookie в одном браузере и переключается на другой браузер, если у них все еще есть файл cookie с локальным общим объектом, cookie будет воспроизводиться в обоих браузерах».

Вы можете сделать это с помощью кэшированного 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 и преобразуйте целые числа в ctx.getImageData строку.

6: Это ваш уникальный идентификатор пользователя, который теперь кэшируется на вашем компьютере пользователя.

Основываясь на том, что вы сказали:

В основном я после распознавания устройства не действительно пользователь

Лучший способ сделать это – отправить MAC-адрес, который является идентификатором NIC.

Вы можете посмотреть этот пост: Как я могу получить MAC и IP-адрес подключенного клиента в PHP?

JavaScript Mac Finder

Вы можете сделать это с etags. Хотя я не уверен, что этот законный закон был подан в суде.

Если вы правильно предупреждаете своих пользователей или у вас есть что-то вроде веб-сайта интрасети, возможно, все в порядке.

Вы можете создать blob для хранения идентификатора устройства …

недостатком является то, что пользователю необходимо загрузить blob ( вы можете принудительно загрузить ), так как браузер не может получить доступ к файловой системе, чтобы напрямую сохранить файл.

Справка:

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

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

Это устраняет необходимость использования файлов cookie и localstorage.

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

И для причины, для оценки функций, которые я предлагаю, в частности, поддержки векторных машин и libsvm .

Отслеживать их во время сеанса или между сеансами?

Если ваш сайт HTTPS Everywhere, вы можете использовать идентификатор сеанса TLS для отслеживания сеанса пользователя

  1. создать плагин подплатной платформы (nsapi) и создать уникальное имя для имени или версии плагина, когда пользователь загрузит его (например, после входа в систему).
  2. предоставить установщик для плагина / установить его на политику

это потребует от пользователя добровольной установки идентификатора.

после установки плагина, отпечаток любого (подключенного к плагину) браузера будет содержать этот конкретный плагин. Чтобы вернуть информацию на сервер, необходим алгоритм для эффективного обнаружения плагина на стороне клиента, в противном случае IE и Firefox> = 28 пользователям потребуется таблица возможных действительных идентификаторов.

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

Пользователи, которые не хотят быть идентифицированными (или их машины), всегда найдут способ предотвратить это.