用户识别无Cookie或本地存储(User recognition without cookies

2019-08-22 05:58发布

我建立一个分析工具,我可以从目前他们的用户代理获取用户的IP地址,浏览器和操作系统。

我不知道是否有检测到相同的用户不使用Cookie或本地存储的可能性? 我不希望在这里的代码示例; 只是在哪里看得更远,一个简单的提示。

忘了提,这将需要跨浏览器兼容,如果是在同一台计算机/设备。 基本上我设备识别不是真正的用户后我。

Answer 1:

介绍

如果我理解正确的话,你需要确定你的人没有一个唯一标识符的用户,所以要通过匹配随机数据找出他们是谁。 你不能存储用户的身份可靠,因为:

  • Cookie可以被删除
  • IP地址可以改变
  • 浏览器可以更改
  • 浏览器缓存可能会被删除

Java applet或COM对象会一直使用的硬件信息的哈希一个简单的解决方案,但这些天人们是如此的安全意识,这将是很难让人们他们的系统上安装这些类型的节目。 这使你坚持使用Cookies和其他类似的工具。

Cookies和其他类似工具

你可能会考虑建立一个数据档案,然后使用概率测试来识别可能的用户 。 这个有用的配置文件可以由以下的某些组合来生成:

  1. IP地址
    • 真实IP地址
    • 代理服务器的IP地址(用户经常使用相同的代理服务器重复)
  2. 饼干
    • HTTP饼干
    • 会话Cookie
    • 第三方Cookie
    • 闪存饼干( 大多数人不知道如何删除这些 )
  3. 网络臭虫(不太可靠,因为错误得到修复,但仍然有用)
    • PDF错误
    • 闪存错误
    • Java的错误
  4. 浏览器
    • 点击追踪(许多用户访问每个访问同一系列的页)
    • 浏览器指纹 - 已安装的插件(人们往往有变化,有些独特的插件集)
    • 高速缓存图像(人们有时会删除Cookie,但留下的缓存图片)
    • 使用斑点
    • 网址(浏览器历史记录或Cookie可能包含独特的用户ID在URL中,如https://stackoverflow.com/users/1226894或http://www.facebook.com/barackobama?fref=ts )
    • 系统字体检测 (这是一个鲜为人知的,但往往是独一无二的密钥签名)
  5. HTML5和Javascript
    • 就是HTML5 LocalStorage
    • HTML5地理位置API和反向地理编码
    • 体系结构,操作系统语言,系统时间,屏幕分辨率等。
    • 网络信息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)实际上是用户1用户2或概率? 并且这两个比赛是可能的?

为了有效地回答这个问题,你需要了解频率与概率格式 ,以及为什么联合概率可能是一个更好的办法。 细节太多进入这里(这就是为什么我给你链接),但是一个很好的例子是医疗诊断向导应用程序 ,它使用的症状的组合,以确定可能的疾病。

认为对于系列作为症状 ,和未知用户作为疾病 ,其包括(在上面的例子B + C + E + G + F + K)的数据资料的数据点的时刻。 通过识别疾病,可以进一步确定一个适当的处理(把这个用户以User1)。

显然,我们已经确定了1种多症状疾病是更容易识别。 事实上,更多的症状 ,我们可以识别,更容易,更准确的诊断我们几乎可以肯定是。

是否有任何其他的选择吗?

当然。 作为替代措施,您可以创建自己的简单评分算法,以及基于它的精确匹配。 这并不像概率高效率,但可能是简单的为您实现。

作为一个例子,考虑这个简单的评分表:

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

对于每一条信息,你可以收集在一个给定的请求,授予相关联得分,然后利用重要性解决冲突时的分数是一样的。

概念验证

对于概念的一个简单证明,请看一看感知 。 感知器是一个RNA模型是通常用于在模式识别的应用程序。 甚至有一个古老的PHP类 ,其完美的实现了它,但你可能会需要修改它为您的目的。

尽管是一个伟大的工具,感知仍然可以返回多个结果(可能的匹配),所以用分数和差异比较仍然是确定最佳的比赛非常有用。

假设

  • 存储每个用户的所有可能的信息(IP,饼干等)
  • 当结果是完全匹配的,加1分
  • 当结果不完全匹配,减1分

期望

  1. 生成RNA标签
  2. 生成随机模拟用户数据库
  3. 产生一个未知的用户
  4. 生成未知用户RNA和值
  5. 该系统将合并RNA的信息,并教感知
  6. 训练感知后,系统将有一组权重
  7. 现在,您可以测试未知用户的模式和感知器会产生一个结果集。
  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)

“d”的print_r的:

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
)

如果调试=真你就可以看到输入(传感器和需要),初始重量,输出(传感器,求和,网络),错误校正和最终权重 。

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

结论

识别用户没有唯一的标识符是不是一个直接的或简单的任务。 你可以通过各种方法从用户收集它依赖于收集随机数据的足够量。

即使你选择不使用人工神经网络,我建议至少使用与优先级和可能性简单的概率矩阵 - 我希望的代码和上面的例子提供给你足够的去上。



Answer 2:

这种技术(检测同一用户无需饼干-甚至没有IP地址)被称为浏览器的指纹 。 基本上你爬约,你可以在浏览器信息 - 更好的效果,可以使用JavaScript,Flash或Java(f.ex.安装的扩展,字体等)来实现的。 在此之后,你可以存储结果散列,如果你想要的。

这不是万无一失的,但是:

看到有一个独特的指纹识别浏览器的83.6%; 在那些与Flash或Java功能,94.2%。 这不包括饼干!

更多信息:

  • https://panopticlick.eff.org/
  • https://wiki.mozilla.org/Fingerprinting
  • https://www.browserleaks.com/


Answer 3:

上述thumbprinting工作,但还是可以承受colisions。

一种方法是添加UID与用户的每个交互的URL。

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

凡在现场的每一个环节,用于此修改。 它类似于ASP.Net使用使用网页之间的表单数据的工作方式。



Answer 4:

你看着Evercookie ? 它可能会或可能不会跨浏览器工作。 从他们的网站的提取物。

“如果用户得到的Cookie在一个浏览和切换到其他浏览器,只要他们仍然有本地共享对象的cookie,cookie将重现于这两种浏览器。”



Answer 5:

你可以用缓存PNG做到这一点,它会有些不可靠(不同的浏览器不同的行为,如果用户清除其缓存,它会失败),但它是一个选项。

1:设置一个存储唯一的用户ID为十六进制字符串数据库

2:创建一个genUser.php(或任何语言)文件生成的用户ID,将其存储在DB,然后创建真彩色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:这是你唯一的用户ID是现在被缓存在用户的计算机上。



Answer 6:

根据你所说的话:

基本上我设备识别不是真正的用户后,我

做到这一点的最佳方式是发送MAC地址是网卡ID。

你可以看看这篇文章: 我怎样才能获得MAC和PHP连接的客户端的IP地址?

JavaScript的Mac Finder上



Answer 7:

您可以使用ETag做。 虽然我不知道这是否合法的一堆诉讼中提出的。

如果你正确地提醒用户,或者如果您有类似的内部网站也可能是好的。



Answer 8:

你可能会创建一个blob存储设备标识符...

不足之处是,用户需要下载BLOB( 你可以强制下载 ),因为浏览器无法访问文件系统直接保存文件。

参考:

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



Answer 9:

效率低下,而且可能会给你想要的结果,将轮询在你身边的API。 具有在其上以一定间隔发送的用户数据的客户端侧的后台进程。 您将需要一个用户标识符发送给您的API。 一旦你有,你可以沿着关联到唯一标识符发送任何信息。

这消除了饼干和localStorage的需要。



Answer 10:

我不能相信, http://browserspy.dk仍未这里所说的! 该网站介绍了许多功能(在模式识别方面),它可以用来建立一个分类。

和原因,评估的特点,我建议支持向量机和LIBSVM尤其如此。



Answer 11:

在会议期间或在会话跟踪他们?

如果您的网站是HTTPS无处不在,你可以使用TLS会话ID来跟踪用户的会话



Answer 12:

  1. 该插件名称或版本创建一个跨平台的虚拟(NSAPI)插件,并生成一个唯一的名称,当用户下载它(例如,登录后)。
  2. 提供安装该插件/每份保单安装

这将要求用户心甘情愿地安装标识符。

一旦安装了该插件后, 指纹任何的(插件启用)浏览器将包含此特定插件。 要返回的信息到服务器,需要一种算法来有效地检测在客户端插件,否则IE和Firefox> = 28个用户将需要的可能的有效识别的表。

这需要一个相对较高的投资进入,这将有可能是由浏览器厂商关闭的技术。 当你能够说服你的用户安装一个插件,也可能有选项,如安装一个本地代理 ,使用VPN或修补网络驱动程序。

不希望用户被识别(或他们的机器)总是会找到一种方法来阻止它。



文章来源: User recognition without cookies or local storage