Reconhecimento do usuário sem cookies ou armazenamento local

132

Estou construindo uma ferramenta analítica e, atualmente, posso obter o endereço IP, o navegador e o sistema operacional do usuário do agente do usuário.

Gostaria de saber se existe a possibilidade de detectar o mesmo usuário sem usar cookies ou armazenamento local? Não estou esperando exemplos de código aqui; apenas uma dica simples de onde procurar mais.

Esqueceu-se de mencionar que precisaria ser compatível com vários navegadores se fosse o mesmo computador / dispositivo. Basicamente, estou atrás do reconhecimento do dispositivo e não do usuário.

slash197
fonte
5
Na verdade, não - pelo menos não, de qualquer maneira que você possa confiar para ser preciso. Talvez um hash dos três seja combinado, no entanto, se mais de uma pessoa em uma casa usar o mesmo navegador e sistema operacional, ele ainda não funcionará. Além disso, a maioria dos ISPs fornece endereços IP dinâmicos, o que significa que eles mudam de vez em quando e também não podem ser confiáveis ​​para fins de identificação.
Jon
2
Então você não sabe o que são sessões. Seu caso de uso é exatamente para o que as sessões foram projetadas. As sessões não têm nada a ver com login ou autenticação. Seu servidor da web informará um cliente para enviar um cookie com um identificador de sessão. Você identifica esse cliente usando o ID da sessão que ele envia.
Homem Código Vs
4
Os cookies ainda funcionariam? Por que você está evitando o uso de cookies?
21713 Baba
2
É realmente simples e eu o uso o tempo todo, peça ao usuário que digite um nome de usuário e uma senha !!!
Amit Kriplani
2
Aqui está uma solução javascript mínima (neste caso, não entre navegadores): github.com/carlo/jquery-browser-fingerprint Eu mencionei isso, porque me levou à noção de que muitos plug-ins estão instalados no navegador por padrão, sem qualquer escolha por parte do usuário. Classificar esses detalhes com cuidado (o que não é uma tarefa pequena, mas ainda assim ...) pode levar a uma propriedade tangível e independente do navegador de uma impressão digital maior baseada em dispositivo.
precisa saber é o seguinte

Respostas:

389

Introdução

Se o entendi corretamente, você precisa identificar um usuário para quem não possui um identificador exclusivo, para descobrir quem eles são combinando dados aleatórios. Você não pode armazenar a identidade do usuário de maneira confiável porque:

  • Cookies podem ser excluídos
  • Endereço IP pode mudar
  • O navegador pode mudar
  • O cache do navegador pode ser excluído

Um Java Applet ou Com Object seria uma solução fácil usando um hash de informações de hardware, mas hoje em dia as pessoas têm tanta segurança que seria difícil convencer as pessoas a instalar esses tipos de programas em seu sistema. Isso deixa você com o uso de cookies e outras ferramentas semelhantes.

Cookies e outras ferramentas similares

Você pode considerar criar um perfil de dados e usar testes de probabilidade para identificar um usuário provável . Um perfil útil para isso pode ser gerado por alguma combinação do seguinte:

  1. Endereço de IP
    • Endereço IP real
    • Endereço IP do proxy (os usuários geralmente usam o mesmo proxy repetidamente)
  2. Biscoitos
  3. Web Bugs (menos confiável porque os bugs são corrigidos, mas ainda são úteis)
    • Bug em PDF
    • Flash Bug
    • Java Bug
  4. Navegadores
    • Acompanhamento de cliques (muitos usuários visitam a mesma série de páginas em cada visita)
    • Impressão digital de navegadores - Plugins instalados (as pessoas geralmente têm conjuntos variados e únicos de plugins)
    • Imagens em cache (às vezes as pessoas excluem seus cookies, mas deixam imagens em cache)
    • Usando Blobs
    • URL (s) (o histórico do navegador ou os cookies podem conter IDs de usuário únicos nos URLs, como https://stackoverflow.com/users/1226894 ou http://www.facebook.com/barackobama?fref=ts )
    • Detecção de fontes do sistema (esta é uma assinatura de chave pouco conhecida, mas geralmente única)
  5. HTML5 e Javascript
    • LocalStorage HTML5
    • API de localização geográfica em HTML5 e geocodificação reversa
    • Arquitetura, idioma do sistema operacional, hora do sistema, resolução de tela etc.
    • API de informações de rede
    • API de status da bateria

Os itens que listei são, obviamente, apenas algumas maneiras possíveis de identificar um usuário de forma exclusiva. Há muito mais.

Com esse conjunto de elementos de dados aleatórios dos quais construir um perfil de dados, o que vem a seguir?

O próximo passo é desenvolver algum Fuzzy Logic , ou, ainda melhor, uma Rede Neural Artificial (que usa a lógica fuzzy). Em qualquer um dos casos, a idéia é treinar seu sistema e, em seguida, combinar seu treinamento com a Inferência Bayesiana para aumentar a precisão de seus resultados.

Rede neural artificial

A biblioteca NeuralMesh para PHP permite gerar redes neurais artificiais. Para implementar a inferência bayesiana, confira os seguintes links:

Neste ponto, você pode estar pensando:

Por que tanta matemática e lógica para uma tarefa aparentemente simples?

Basicamente, porque não é uma tarefa simples . O que você está tentando alcançar é, de fato, Probabilidade pura . Por exemplo, considerando os seguintes usuários conhecidos:

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

Quando você recebe os seguintes dados:

B + C + E + G + F + K

A pergunta que você está fazendo essencialmente é:

Qual é a probabilidade de os dados recebidos (B + C + E + G + F + K) serem realmente Usuário1 ou Usuário2? E qual dessas duas partidas é mais provável?

Para responder efetivamente a essa pergunta, é necessário entender o formato de frequência versus probabilidade e por que a probabilidade conjunta pode ser uma abordagem melhor. Os detalhes são muitos para entrar aqui (e é por isso que eu estou fornecendo links), mas um bom exemplo seria um Aplicativo para Assistente de Diagnóstico Médico , que usa uma combinação de sintomas para identificar possíveis doenças.

Pense por um momento na série de pontos de dados que compõem seu Perfil de Dados (B + C + E + G + F + K no exemplo acima) como Sintomas e Usuários Desconhecidos como Doenças . Ao identificar a doença, você pode identificar ainda um tratamento apropriado (tratar esse usuário como Usuário1).

Obviamente, é mais fácil identificar uma doença para a qual identificamos mais de 1 sintoma . De fato, quanto mais sintomas pudermos identificar, mais fácil e preciso será nosso diagnóstico.

Há alguma outra alternativa?

Claro. Como medida alternativa, você pode criar seu próprio algoritmo de pontuação simples e basear-se em correspondências exatas. Isso não é tão eficiente quanto a probabilidade, mas pode ser mais simples de implementar.

Como exemplo, considere este gráfico de pontuação simples:

+ ------------------------- + -------- + ------------ +
| Propriedade Peso Importância
+ ------------------------- + -------- + ------------ +
| Endereço IP real | 60 5
| Endereço IP do proxy usado | 40 4
| Cookies HTTP | 80 8
| Cookies de sessão | 80 6
| Cookies de terceiros | 60 4
| Cookies em Flash | 90 7
| Bug em PDF | 20 1 |
| Bug em Flash | 20 1 |
| Bug do Java | 20 1 |
| Páginas Frequentes | 40 1 |
| Impressão digital de navegadores | 35 2
| Plugins instalados | 25 1 |
| Imagens em cache | 40 3
| URL 60 4
| Detecção de fontes do sistema | 70 4
| Armazenamento local | 90 8
| Geolocalização | 70 6
| AOLTR 70 4
| API de informações de rede | 40 3
| API de status da bateria | 20 1 |
+ ------------------------- + -------- + ------------ +

Para cada informação que você pode reunir em uma determinada solicitação, conceda a pontuação associada e use a Importância para resolver conflitos quando as pontuações forem iguais.

Prova de conceito

Para uma simples prova de conceito, dê uma olhada no Perceptron . O Perceptron é um modelo de RNA geralmente usado em aplicações de reconhecimento de padrões. Existe até uma classe PHP antiga que a implementa perfeitamente, mas você provavelmente precisaria modificá-la para seus propósitos.

Apesar de ser uma ótima ferramenta, o Perceptron ainda pode retornar vários resultados (possíveis correspondências); portanto, o uso de uma comparação de Pontuação e Diferença ainda é útil para identificar a melhor dessas correspondências.

Premissas

  • Armazene todas as informações possíveis sobre cada usuário (IP, cookies etc.)
  • Onde o resultado é uma correspondência exata, aumente a pontuação em 1
  • Onde o resultado não for uma correspondência exata, diminua a pontuação em 1

Expectativa

  1. Gere marcadores de RNA
  2. Gere usuários aleatórios emulando um banco de dados
  3. Gere um único usuário desconhecido
  4. Gerar RNA e valores de usuário desconhecido
  5. O sistema mesclará informações de RNA e ensinará o Perceptron
  6. Após treinar o Perceptron, o sistema terá um conjunto de pesos
  7. Agora você pode testar o padrão do usuário desconhecido e o Perceptron produzirá um conjunto de resultados.
  8. Armazenar todos os resultados positivos
  9. Classifique as partidas primeiro por Pontuação e depois por Diferença (conforme descrito acima)
  10. Gera as duas correspondências mais próximas ou, se nenhuma correspondência for encontrada, gera resultados vazios

Código de Prova de Conceito

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

Resultado:

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

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

Se Debug = true, você poderá ver Entrada (Sensor e Desejado), Pesos Iniciais, Saída (Sensor, Soma, Rede), Erro, Correção e Pesos Finais .

+----+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+-----+----+---------+---------+---------+---------+---------+---------+---------+---------+---------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----------+
| 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 a x20 representam os recursos convertidos pelo código.

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

Aqui está uma demonstração online

Classe usada:

class Profile {
    public $name, $data = array(), $score, $diff, $base;

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

    public function setScore($score, $diff) {
        $this->score = $score / $this->base;
        $this->diff = $diff / $this->base;
    }
}

Classe Perceptron modificada

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

Conclusão

Identificar um usuário sem um Identificador Único não é uma tarefa direta ou simples. depende da coleta de uma quantidade suficiente de dados aleatórios, que você pode coletar do usuário por vários métodos.

Mesmo se você optar por não usar uma rede neural artificial, sugiro pelo menos usar uma matriz de probabilidade simples com prioridades e probabilidades - e espero que o código e os exemplos fornecidos acima lhe dêem o suficiente para continuar.

Baba
fonte
@Baba O que você quer dizer com "Usando Blobs" para fazer a impressão digital de um navegador?
billmalarky
1
@Baba Como alguém usaria isso para fazer impressões digitais em um navegador? Basta verificar o que está atualmente nele a qualquer momento?
billmalarky
@Baba, ótimo trabalho, sempre tentei ter uma estratégia de vários níveis para identificar um usuário, mas como você disse que o cache pode ser limpo, os IPs são alterados, os usuários protegidos por proxies ou NAT - especialmente essas pessoas -, os cookies excluídos etc. .mas mesmo com todo esse esforço, é uma questão de probabilidade, também se o usuário ruim estiver usando o navegador Tor, por exemplo, a maioria , se não todas, as estratégias de detecção mencionadas não funcionarão. Eu gostava browserleaks.com mas com Tor tudo voltou indefinido ou desconhecida
Mi-Criatividade
Apenas uma Nota destinada apenas a "remover um pouco de poeira" desta gema de uma publicação: Lista de links quebrados a partir de 07.09.17: - Implement Bayesian inference using PHP, todas as três partes. - Frequency vs Probability - Joint Probability -Input (Sensor & Desired), Initial Weights, Output (Sensor, Sum, Network), Error, Correction and Final Weights
Ziezi
28

Essa técnica (para detectar os mesmos usuários sem cookies - ou mesmo sem o endereço IP) é chamada de impressão digital do navegador . Basicamente, você rastreia o máximo possível de informações sobre o navegador - melhores resultados podem ser alcançados com javascript, flash ou java (por exemplo, extensões instaladas, fontes, etc.). Depois disso, você pode armazenar os resultados com hash, se desejar.

Não é infalível, mas:

83,6% dos navegadores vistos tinham uma impressão digital única; entre aqueles com Flash ou Java ativado, 94,2%. Isso não inclui cookies!

Mais informações:

pozs
fonte
eu acho que ainda é a resposta. se você precisar identificar um dispositivo, precisará apenas obter esses dados - por exemplo, SO, extensões genéricas (e suas versões), fontes instaladas, etc ...
pozs
Isso não vai funcionar bem. Todo navegador suporta sessões e cookies. Use a ferramenta certa para o trabalho.
Homem Código Vs
1
@ slash197 e quanto ao cache de arquivos? Quero dizer, usar mídia flash transparente 1px x 1px, juntamente com um arquivo xml contendo um ID gerado exclusivo (o xml deve ser criado uma vez no servidor antes de ser baixado para o HD local do usuário) dessa maneira, mesmo que o usuário exclua cookies ou faça logout, você ainda pode ter uma ponte usando o script de ação método sendAndLoad.
Mbarry
O mínimo de alteração afetará o resultado do hash. por exemplo, a versão do shock wave player. solução possível com o arquivo de cache xml armazenado localmente com chave única gerada + mídia flash 1px x 1px oculta (script de ação) no navegador, assim você se livra dos cookies, problema de expiração da sessão, se esse era o problema principal. você ainda pode ter a ponte entre o banco de dados sql e a chave na máquina local do usuário.
precisa saber é o seguinte
@Mbarry Eu não sou muito fã de flash, mas se no navegador houver um complemento de bloqueio de flash, como eu tenho, a mídia flash de 1x1 pixel seria desativada, estou empolgado?
precisa saber é o seguinte
7

A impressão digital acima mencionada funciona, mas ainda pode sofrer colisões.

Uma maneira é adicionar o UID ao URL de cada interação com o usuário.

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

Onde todos os links no site são adaptados com este modificador. É semelhante à maneira como o ASP.Net costumava trabalhar usando dados FORM entre páginas.

Justin Alexander
fonte
Pensei nisso, mas essa é a maneira mais fácil para um usuário para modificá-lo
slash197
1
não do id é um hash auto-referenciado. Torna-o criptograficamente seguro.
11113 Justin13
Além disso, esse método é bom quando alguém está navegando no site, mas como você propõe lidar com o caso quando um usuário que retorna depois de uma semana e simplesmente digita o endereço do site, sem identificação?
slash197
@ slash197 nesse caso, por que você não diz ao usuário para fazer login, que é o que acontece mesmo quando o usuário exclui os cookies.
precisa saber é o seguinte
6

Você já olhou para Evercookie ? Pode ou não funcionar nos navegadores. Um extrato do site deles.

"Se um usuário for cozinhado em um navegador e alternar para outro, contanto que ainda possua o cookie Local Shared Object, o cookie será reproduzido nos dois navegadores."

Alexis Tyler
fonte
Gostaria de saber se ele funciona com JavaScript desativado. Você tem alguma experiência?
Voitcus
É chamado evercookie por um motivo, funcionará não importa o quê. É quase impossível para eles remover o cookie.
Alexis Tyler
Não vai funcionar, não importa o quê. Desde a primeira linha da descrição: 'evercookie é uma API javascript ...'. Não funcionará se o javascript estiver desativado.
gdw2
Não precisa ser desativado. Ghostery e uBlock deixam cair evercookie
opengrid 19/05/19
3

Você pode fazer isso com um png em cache, seria um pouco confiável (navegadores diferentes se comportam de maneira diferente e falhará se o usuário limpar o cache), mas é uma opção.

1: configure um banco de dados que armazene um ID de usuário exclusivo como uma sequência hexadecimal

2: crie um arquivo genUser.php (ou qualquer outro idioma) que gere um ID de usuário, armazene-o no banco de dados e, em seguida, crie um .png de cor verdadeira a partir dos valores dessa sequência hexadecimal (cada pixel terá 4 bytes) e retornará isso para o navegador. Certifique-se de definir o tipo de conteúdo e os cabeçalhos de cache.

3: no HTML ou JS, crie uma imagem como <img id='user_id' src='genUser.php' />

4: desenhe essa imagem em uma tela ctx.drawImage(document.getElementById('user_id'), 0, 0);

5: leia os bytes dessa imagem usando ctx.getImageData e converta os números inteiros em uma sequência hexadecimal.

6: esse é o seu ID de usuário exclusivo, agora armazenado em cache no computador dos usuários.

hobberwickey
fonte
Ele quer algo que possa rastrear o usuário "entre navegadores", que não funcionará aqui (cada navegador possui seu próprio banco de dados de cache).
EricLaw 30/09
Onde você está vendo isso, a pergunta dele pede apenas "Esqueci de mencionar que precisaria ser compatível com vários navegadores", ou seja, trabalhar em qualquer navegador.
Hbberwickey
Sua pergunta está mal escrita. I'm after device recognitioné a oferta para o que ele quer, e ele elabora aqui: stackoverflow.com/questions/15966812/…
EricLaw 3/15
2

Com base no que você disse:

Basicamente, estou atrás do reconhecimento do dispositivo e não do usuário

A melhor maneira de fazer isso é enviar o endereço mac, que é o ID da NIC.

Você pode dar uma olhada neste post: Como posso obter o MAC e o endereço IP de um cliente conectado em PHP?

Mehdi Karamosly
fonte
Desculpe, mas o NIC ID é fácil de falsificar. Definitivamente, não é o melhor caminho.
13/07/2015
A impressão digital do navegador @asgs talvez seja melhor, ou qual seria a melhor maneira na sua opinião?
Mehdi Karamosly
Não há melhor maneira, essa é a parte triste disso. No entanto, isso e o Browser FingerPrinting em combinação com o estudo de Probabilidade que Baba apresentou acima seriam os melhores na minha opinião.
14/07/2015
1

Você pode fazer isso com etags. Embora eu não tenha certeza se esse processo legal como um monte de ações foram ajuizadas.

Se você avisar corretamente seus usuários ou se você tiver algo como um site de intranet, pode estar tudo bem.

Brian McGinity
fonte
Etags não são compatíveis com vários navegadores.
slash197
1
Etags fazem parte da especificação HTTP / 1.1. Todos os navegadores populares suportam etags, você precisaria praticamente escrever seu próprio navegador para não suportar cabeçalhos ETag / If-None-Match.
Brian McGinity
Eu não disse que não suporta, eu disse que não é compatível com vários navegadores. Se uma tag é salva no Firefox, ela não está disponível no chrome, portanto o conteúdo será baixado novamente, pois não há cache.
slash197
Agora eu entendo o que você estava dizendo. Você está certo. Cada navegador possui seu próprio armazenamento em cache, portanto, etags diferentes.
precisa saber é o seguinte
0

Ineficiente, mas pode fornecer os resultados desejados, seria pesquisar uma API do seu lado. Tenha um processo em segundo plano no lado do cliente que envie os dados do usuário em um intervalo. Você precisará de um identificador de usuário para enviar para sua API. Depois que você tiver, poderá enviar as informações associadas a esse identificador exclusivo.

Isso elimina a necessidade de cookies e armazenamento local.

rexposadas
fonte
0

Não acredito, http://browserspy.dk ainda não foi mencionado aqui! O site descreve muitos recursos (em termos de reconhecimento de padrões), que podem ser usados ​​para criar um classificador.

E de causa, para avaliar os recursos, sugiro Support Vector Machines e libsvm em particular.

Valentin Heinitz
fonte
0

Rastreá-los durante uma sessão ou entre sessões?

Se o seu site for HTTPS Everywhere, você poderá usar o ID da sessão TLS para rastrear a sessão do usuário

Neil McGuigan
fonte
1
a questão aqui é como?
user455318
-2
  1. crie um plug-in fictício de plataforma cruzada (nsapi) e gere um nome exclusivo para o nome ou versão do plug-in quando o usuário fizer o download (por exemplo, após o login).
  2. forneça um instalador para o plug-in / instale-o por política

isso exigirá que o usuário instale voluntariamente o identificador.

Depois que o plug-in é instalado, a impressão digital de qualquer navegador (ativado por plug-in) conterá esse plug-in específico. Para retornar as informações para um servidor, é necessário um algoritmo para detectar efetivamente o plug-in no lado do cliente; caso contrário, os usuários do IE e Firefox> = 28 precisarão de uma tabela de possíveis identificações válidas.

Isso requer um investimento relativamente alto em uma tecnologia que provavelmente será desativada pelos fornecedores de navegadores. Quando você consegue convencer seus usuários a instalar um plug-in, também pode haver opções como instalar um proxy local , usar vpn ou corrigir os drivers de rede.

Os usuários que não desejam ser identificados (ou suas máquinas) sempre encontrarão uma maneira de evitá-lo.

aec8adaikaeNg6hey2oof8otai9quo
fonte
Oi bem-vindo ao estouro de pilha. Observe; this will require the user to willingly install the identifier.provavelmente não é o que o pôster original (OP) significava.
Stefan