Giriş
Sizi doğru anlarsam, Benzersiz Tanımlayıcınız olmayan bir kullanıcıyı belirlemeniz gerekir, bu nedenle Rastgele Verileri eşleştirerek kim olduklarını bulmak istersiniz. Kullanıcının kimliğini güvenilir şekilde saklayamazsınız çünkü:
- Çerezler silinebilir
- IP adresi değişebilir
- Tarayıcı Değiştirebilir
- Tarayıcı Önbelleği silinebilir
Bir Java Uygulaması veya Com Nesnesi, bir donanım bilgisi karması kullanarak kolay bir çözüm olabilirdi, ancak günümüzde insanlar o kadar güvenlik bilincindedir ki, bu tür programları sistemlerine kurmaları zor olacaktır. Bu, sizi Çerezleri ve diğer benzer araçları kullanmaya mecbur bırakır.
Çerezler ve diğer benzer araçlar
Bir Veri Profili oluşturmayı ve ardından bir Olası Kullanıcıyı belirlemek için Olasılık testlerini kullanmayı düşünebilirsiniz . Bunun için yararlı bir profil, aşağıdakilerin bir kombinasyonu ile oluşturulabilir:
- IP adresi
- Gerçek IP Adresi
- Proxy IP Adresi (kullanıcılar genellikle aynı proxy'yi tekrar tekrar kullanır)
- Kurabiye
- Web Hataları (daha az güvenilir çünkü hatalar giderilir, ancak yine de yararlıdır)
- PDF Hatası
- Flaş Hata
- Java Hatası
- Tarayıcılar
- Tıklama İzleme (birçok kullanıcı her ziyarette aynı sayfa serisini ziyaret eder)
- Tarayıcılar Parmak İzi - Yüklü Eklentiler (insanlar genellikle çeşitli, biraz benzersiz eklenti setlerine sahiptir)
- Önbelleğe Alınmış Görüntüler (insanlar bazen çerezlerini siler ancak önbelleğe alınmış görüntüleri bırakır)
- Blobları Kullanma
- URL (ler) (tarayıcı geçmişi veya çerezler, https://stackoverflow.com/users/1226894 veya http://www.facebook.com/barackobama?fref=ts gibi URL'lerde benzersiz kullanıcı kimlikleri içerebilir )
- Sistem Yazı Tipleri Algılama (bu, az bilinen ancak genellikle benzersiz bir anahtar imzasıdır)
- HTML5 ve Javascript
- HTML5 LocalStorage
- HTML5 Geolocation API ve Ters Coğrafi Kodlama
- Mimari, İşletim Sistemi Dili, Sistem Saati, Ekran Çözünürlüğü vb.
- Network Information API
- Pil Durumu API
Listelediğim öğeler, elbette, bir kullanıcının benzersiz bir şekilde tanımlanmasının yalnızca birkaç olası yolu. Daha çok var.
Veri Profili oluşturmak için bu Rastgele Veri öğeleri kümesiyle, sırada ne var?
Bir sonraki adım, biraz Bulanık Mantık veya daha iyisi Yapay Sinir Ağı (bulanık mantık kullanan) geliştirmektir. Her iki durumda da fikir, sisteminizi eğitmek ve ardından sonuçlarınızın doğruluğunu artırmak için eğitimini Bayesian Çıkarımı ile birleştirmektir .
NeuralMesh PHP için kütüphane size Yapay Sinir Ağları oluşturmasına olanak sağlar. Bayes Çıkarımını uygulamak için aşağıdaki bağlantılara göz atın:
Bu noktada şunları düşünüyor olabilirsiniz:
Görünüşte basit bir görev için neden bu kadar Matematik ve Mantık?
Temel olarak, çünkü bu basit bir görev değil . Başarmaya çalıştığınız şey aslında Saf Olasılıktır . Örneğin, aşağıdaki bilinen kullanıcılar verildiğinde:
User1 = A + B + C + D + G + K
User2 = C + D + I + J + K + F
Aşağıdaki verileri aldığınızda:
B + C + E + G + F + K
Esasen sorduğunuz soru şudur:
Alınan verilerin (B + C + E + G + F + K) gerçekte Kullanıcı1 veya Kullanıcı2 olma olasılığı nedir? Ve bu iki maçtan hangisi en olası?
Bu soruyu etkili bir şekilde yanıtlayabilmek için, Frekansa karşı Olasılık Biçimini ve Ortak Olasılığın neden daha iyi bir yaklaşım olabileceğini anlamanız gerekir . Ayrıntılar buraya girmek için çok fazla (bu yüzden size bağlantılar veriyorum), ancak buna iyi bir örnek Tıbbi Teşhis Sihirbazı Başvurusu olabilir. olası hastalıkları tanımlamak için semptomların bir kombinasyonunu kullanan bir olabilir.
Veri Profilinizi (yukarıdaki örnekte B + C + E + G + F + K) Semptomlar ve Hastalık Olarak Bilinmeyen Kullanıcılar olarak oluşturan veri noktaları serisini bir an için düşünün . Hastalığı tanımlayarak, uygun bir tedaviyi daha da tanımlayabilirsiniz (bu kullanıcıyı Kullanıcı1 olarak ele alın).
Açıkçası, 1'den fazla Semptom belirlediğimiz bir Hastalığın tanımlanması daha kolaydır. Aslında, daha fazla Semptom belirledikçe, teşhisimizin daha kolay ve daha doğru olacağı neredeyse kesindir.
Başka alternatif var mı?
Elbette. Alternatif bir önlem olarak, kendi basit puanlama algoritmanızı oluşturabilir ve bunu tam eşleşmelere dayandırabilirsiniz. Bu, olasılık kadar verimli değildir, ancak uygulaması sizin için daha basit olabilir.
Örnek olarak, şu basit puan çizelgesini düşünün:
+ ------------------------- + -------- + ------------ +
| Emlak | Ağırlık | Önemi |
+ ------------------------- + -------- + ------------ +
| Gerçek IP adresi | 60 | 5 |
| Kullanılan proxy IP adresi | 40 | 4 |
| HTTP Çerezleri | 80 | 8 |
| Oturum Çerezleri | 80 | 6 |
| 3. Taraf Çerezleri | 60 | 4 |
| Flash Çerezler | 90 | 7 |
| PDF Hatası | 20 | 1 |
| Flaş Hata | 20 | 1 |
| Java Hatası | 20 | 1 |
| Sık Sayfalar | 40 | 1 |
| Tarayıcılar Parmak İzi | 35 | 2 |
| Yüklü Eklentiler | 25 | 1 |
| Önbelleğe Alınan Resimler | 40 | 3 |
| URL | 60 | 4 |
| Sistem Yazı Tipleri Algılama | 70 | 4 |
| Yerel depolama | 90 | 8 |
| Coğrafi Konum | 70 | 6 |
| AOLTR | 70 | 4 |
| Ağ Bilgileri API | 40 | 3 |
| Pil Durumu API | 20 | 1 |
+ ------------------------- + -------- + ------------ +
Belirli bir talep üzerine toplamak bilgi her parça için, ödül ilişkili puanı, daha sonra kullanmak Önemi puanları aynı olduğunda çözmek çatışmalar.
Kavramın ispatı
Basit bir kavram kanıtı için lütfen Perceptron'a bir göz atın . Perceptron, genellikle örüntü tanıma uygulamalarında kullanılan bir RNA Modelidir . Hatta onu mükemmel bir şekilde uygulayan eski bir PHP Sınıfı vardır, ancak muhtemelen amaçlarınız için onu değiştirmeniz gerekecektir.
Harika bir araç olmasına rağmen, Perceptron yine de birden fazla sonuç (olası eşleşmeler) döndürebilir, bu nedenle bir Puan ve Fark karşılaştırması kullanmak , bu eşleşmelerin en iyisini belirlemek için yine de yararlıdır .
Varsayımlar
- Her kullanıcıyla ilgili olası tüm bilgileri (IP, çerezler vb.) Saklayın.
- Sonuç tam bir eşleşme olduğunda, puanı 1 artırın
- Sonucun tam eşleşme olmadığı durumlarda, puanı 1 azaltın
beklenti
- RNA etiketleri oluşturun
- Veritabanını taklit eden rastgele kullanıcılar oluşturun
- Tek bir Bilinmeyen kullanıcı oluşturun
- Bilinmeyen Kullanıcı RNA'sı ve Değerleri Oluşturun
- Sistem, RNA bilgilerini birleştirecek ve Perceptron'u öğretecektir.
- Perceptron'u eğittikten sonra, sistem bir dizi ağırlığa sahip olacaktır.
- Artık Bilinmeyen kullanıcının modelini test edebilirsiniz ve Perceptron bir sonuç kümesi oluşturacaktır.
- Tüm Pozitif eşleşmeleri sakla
- Eşleşmeleri önce Skor'a, ardından Farka göre sıralayın (yukarıda açıklandığı gibi)
- En yakın iki eşleşmenin çıktısını alın veya hiçbir eşleşme bulunamazsa boş sonuçlar verir
Kavram Kanıtı Kodu
$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 ";
}
Çıktı:
Possible Match D (0.7416|0.16853),C (0.5393|0.2809)
"D" için 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
)
Hata Ayıklama = true ise Giriş (Sensör ve İstenen), Başlangıç Ağırlıkları, Çıktı (Sensör, Toplam, Ağ), Hata, Düzeltme ve Son Ağırlıkları görebilirsiniz .
+----+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+-----+----+---------+---------+---------+---------+---------+---------+---------+---------+---------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----+----+----+----+----+----+----+----+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----------+
| 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, kod tarafından dönüştürülen özellikleri temsil eder.
// Get RNA Labels
$labels = array();
$n = 1;
foreach ( $features as $k => $v ) {
$labels[$k] = "x" . $n;
$n ++;
}
İşte çevrimiçi bir demo
Kullanılan Sınıf:
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;
}
}
Değiştirilmiş Perceptron Sınıfı
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
Sonuç
Benzersiz Tanımlayıcı olmadan bir kullanıcıyı tanımlamak, basit veya basit bir iş değildir. kullanıcıdan çeşitli yöntemlerle toplayabileceğiniz yeterli miktarda Rastgele Verinin toplanmasına bağlıdır.
Yapay Sinir Ağını kullanmamayı seçseniz bile, en azından öncelikleri ve olasılıkları olan Basit Olasılık Matrisi kullanmanızı öneririm - umarım yukarıda verilen kod ve örnekler size devam etmek için yeterince verir.