쿠키 또는 로컬 스토리지가없는 사용자 인식


132

분석 도구를 작성 중이며 현재 사용자 에이전트에서 사용자의 IP 주소, 브라우저 및 운영 체제를 가져올 수 있습니다.

쿠키 나 로컬 스토리지를 사용하지 않고 동일한 사용자를 감지 할 수 있는지 궁금합니다. 여기서 코드 예제를 기대하지 않습니다. 더 자세히 살펴볼 간단한 힌트입니다.

동일한 컴퓨터 / 장치 인 경우 브라우저 간 호환이 필요하다는 것을 언급하지 않았습니다. 기본적으로 나는 장치 인식 후에 실제로 사용자가 아닙니다.


5
사실은 아닙니다-적어도 당신이 정확하다고 의지 할 수있는 방법은 아닙니다. 세 가지가 모두 해시 일 수도 있지만 한 집에있는 두 명 이상의 사람이 동일한 브라우저와 OS를 사용하는 경우 여전히 작동하지 않습니다. 또한 대부분의 ISP는 동적 IP 주소를 제공합니다. 즉, 자주 변경되므로 식별 목적으로도 신뢰할 수 없습니다.
Jon

2
그럼 당신은 세션이 무엇인지 모른다. 사용 사례는 정확히 어떤 세션을 위해 설계된 것입니다. 세션은 로그인 또는 인증과 관련이 없습니다. 웹 서버는 클라이언트에게 세션 식별자가있는 쿠키를 보내도록 지시합니다. 그들이 보낸 세션 ID를 사용하여 해당 클라이언트를 식별합니다.
Man Vs Code

4
쿠키는 여전히 작동합니까? 쿠키를 사용하지 않는 이유는 무엇입니까?
Baba

2
정말 간단하고 항상 사용하므로 사용자에게 사용자 이름과 비밀번호를 입력하도록 요청하십시오 !!!
Amit Kriplani

2
여기에 최소한의 자바 스크립트 솔루션 (이 경우 비 크로스 브라우저)입니다 : github.com/carlo/jquery-browser-fingerprint 이 많은 플러그인은 기본적으로 크로스 브라우저가 설치되어 있다는 생각에 나를 데리고 있기 때문에하지 않고, 나는 그것을 언급 사용자의 선택. 그것들을 조심스럽게 분류하면 (작은 작업은 아니지만 여전히 ...) 잠재적으로 더 큰 장치 기반 지문의 브라우저에 무관 한 속성을 초래할 수 있습니다.
hexalys

답변:


389

소개

올바르게 이해하면 고유 식별자가없는 사용자를 식별해야하므로 임의 데이터와 일치하여 누구인지 파악해야합니다. 다음과 같은 이유로 사용자의 신원을 안정적으로 저장할 수 없습니다.

  • 쿠키 삭제 가능
  • IP 주소 변경 가능
  • 브라우저 변경 가능
  • 브라우저 캐시가 삭제 될 수 있습니다

Java Applet 또는 Com Object는 하드웨어 정보의 해시를 사용하는 쉬운 솔루션 이었지만 요즘 사람들은 보안을 인식하여 사람들이 시스템에 이러한 종류의 프로그램을 설치하기가 어려울 수 있습니다. 쿠키 및 기타 유사한 도구를 사용하는 데 어려움이 있습니다.

쿠키 및 기타 유사한 도구

데이터 프로파일을 작성한 다음 확률 테스트를 사용하여 가능한 사용자 를 식별 할 수 있습니다. 이에 유용한 프로파일은 다음을 조합하여 생성 할 수 있습니다.

  1. IP 주소
    • 실제 IP 주소
    • 프록시 IP 주소 (사용자는 종종 동일한 프록시를 반복적으로 사용함)
  2. 쿠키
  3. 웹 버그 (버그가 수정되었으므로 안정성은 낮지 만 여전히 유용함)
    • PDF 버그
    • 플래시 버그
    • 자바 버그
  4. 브라우저
    • 클릭 추적 (많은 사용자가 각 방문에서 동일한 일련의 페이지를 방문)
    • 브라우저 지문-설치된 플러그인 (사람들은 다양하고 다소 독특한 플러그인 세트를 가지고 있음)
    • 캐시 된 이미지 (사람들은 때때로 쿠키를 삭제하지만 캐시 된 이미지는 남습니다)
    • 블롭 사용
    • URL (브라우저 기록 또는 쿠키에는 https://stackoverflow.com/users/1226894 또는 http://www.facebook.com/barackobama?fref=ts 와 같은 URL에 고유 한 사용자 ID가 포함될 수 있음 )
    • 시스템 글꼴 감지 (이는 거의 알려지지 않았지만 고유 한 키 서명 임)
  5. HTML5 및 자바 스크립트
    • HTML5 LocalStorage
    • HTML5 지리적 위치 API 및 역 지오 코딩
    • 아키텍처, OS 언어, 시스템 시간, 화면 해상도 등
    • 네트워크 정보 API
    • 배터리 상태 API

물론 나열된 항목은 사용자를 고유하게 식별 할 수있는 몇 가지 가능한 방법입니다. 더 많은 것이 있습니다.

이 랜덤 데이터 요소 집합을 사용하여 데이터 프로필을 작성하면 다음은 무엇입니까?

다음 단계는 퍼지 로직 또는 인공 신경 네트워크 (퍼지 로직을 사용하는)를 개발하는 것입니다. 두 경우 모두 시스템을 훈련시킨 다음 베이지안 추론 과 훈련을 결합 하여 결과의 ​​정확성을 높이는 것이 좋습니다.

인공 신경망

NeuralMesh의 PHP를위한 라이브러리는 인공 신경망을 생성 할 수 있습니다. 베이지안 추론을 구현하려면 다음 링크를 확인하십시오.

이 시점에서 다음을 생각할 수 있습니다.

겉보기에 간단한 작업에 왜 수학과 논리가 그렇게 많은가?

기본적으로 간단한 작업아니기 때문 입니다. 실제로 달성하려는 것은 순수 확률 입니다. 예를 들어, 다음과 같은 알려진 사용자가있는 경우 :

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

다음과 같은 데이터가 수신되면 :

B + C + E + G + F + K

본질적으로 묻는 질문은 다음과 같습니다.

수신 된 데이터 (B + C + E + G + F + K)가 실제로 User1 또는 User2 일 확률은 얼마입니까? 그리고 그 두 경기 중 가장 가능성이 높은 것은 무엇입니까?

이 질문에 효과적으로 대답하려면 빈도 대 확률 형식 과 왜 공동 확률 이 더 나은 접근 방식 인지 이해해야 합니다. 자세한 내용은 여기에 도달하기에는 너무 많지만 (링크를 제공하는 이유), 좋은 예는 증상의 조합을 사용하여 가능한 질병을 식별 하는 의료 진단 마법사 응용 프로그램 입니다.

데이터 프로필 (위의 예에서 B + C + E + G + F + K)을 증상으로 , 알 수없는 사용자를 질병으로 구성하는 일련의 데이터 포인트를 생각해보십시오 . 질병을 식별하여 적절한 치료법을 추가로 식별 할 수 있습니다 (이 사용자를 User1로 처리).

분명히, 우리가 하나 이상의 증상을 식별 한 질병 은 쉽게 식별 할 수 있습니다. 실제로, 우리가 식별 할 수있는 증상 이 많을수록 진단이 더 쉽고 정확합니다.

다른 대안이 있습니까?

물론이야. 대안 측정으로, 당신은 당신의 자신의 간단한 점수 알고리즘을 생성하고 정확한 일치를 기반으로 할 수 있습니다. 이것은 확률만큼 효율적이지 않지만 구현하기가 더 간단 할 수 있습니다.

예를 들어,이 간단한 스코어 차트를 고려하십시오.

+ ------------------------- + -------- + -------------- +
| 부동산 | 무게 | 중요성 |
+ ------------------------- + -------- + -------------- +
| 실제 IP 주소 | 60 | 5 |
| 사용 된 프록시 IP 주소 | 40 | 4 |
| HTTP 쿠키 | 80 | 8 |
| 세션 쿠키 | 80 | 6 |
| 타사 쿠키 | 60 | 4 |
| 플래시 쿠키 | 90 | 7 |
| PDF 버그 | 20 | 1 |
| 플래시 버그 | 20 | 1 |
| 자바 버그 | 20 | 1 |
| 잦은 페이지 | 40 | 1 |
| 브라우저 지문 | 35 | 2 |
| 설치된 플러그인 | 25 | 1 |
| 캐시 된 이미지 | 40 | 3 |
| URL | 60 | 4 |
| 시스템 글꼴 감지 | 70 | 4 |
| 로컬 스토리지 | 90 | 8 |
| 지리적 위치 | 70 | 6 |
| AOLTR | 70 | 4 |
| 네트워크 정보 API | 40 | 3 |
| 배터리 상태 API | 20 | 1 |
+ ------------------------- + -------- + -------------- +

특정 요청에 따라 수집 할 수있는 각 정보에 대해 관련 점수를 부여한 다음 중요도 가 동일하면 점수 를 사용 하여 충돌을 해결하십시오.

개념의 증거

간단한 개념 증명을 보려면 Perceptron을 살펴보십시오 . 퍼셉트론은 일반적으로 패턴 인식 애플리케이션에 사용되는 RNA 모델 입니다. 완벽하게 구현 하는 오래된 PHP 클래스도 있지만 목적에 맞게 수정해야 할 수도 있습니다.

훌륭한 도구 임에도 불구하고 Perceptron은 여전히 ​​여러 결과 (가능한 일치 항목)를 반환 할 수 있으므로 점수 및 차이 비교를 사용하면 해당 일치 항목을 가장 잘 식별 할 수 있습니다 .

가정

  • 각 사용자 (IP, 쿠키 등)에 대한 가능한 모든 정보를 저장하십시오.
  • 결과가 정확히 일치하면 점수를 1 씩 증가시킵니다.
  • 결과가 정확히 일치하지 않으면 점수를 1 씩 줄입니다.

기대

  1. RNA 라벨 생성
  2. 데이터베이스를 에뮬레이트하는 임의의 사용자 생성
  3. 알 수없는 단일 사용자 생성
  4. 알 수없는 사용자 RNA 및 값 생성
  5. 이 시스템은 RNA 정보를 병합하고 퍼셉트론을 가르칩니다
  6. 퍼셉트론 훈련 후, 시스템은 일련의 가중치를 갖습니다
  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)

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

Debug = true이면 입력 (센서 및 원하는), 초기 무게, 출력 (센서, 합계, 네트워크), 오류, 수정 및 최종 무게를 볼 수 있습니다.

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

x1 ~ x20은 코드로 변환 된 기능을 나타냅니다.

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

여기 온라인 데모가 있습니다

사용 된 클래스 :

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

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

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

수정 된 퍼셉트론 클래스

class Perceptron {
    private $w = array();
    private $dw = array();
    public $debug = false;

    private function initialize($colums) {
        // Initialize perceptron vars
        for($i = 1; $i <= $colums; $i ++) {
            // weighting vars
            $this->w[$i] = 0;
            $this->dw[$i] = 0;
        }
    }

    function train($input, $alpha, $teta) {
        $colums = count($input[0]) - 1;
        $weightCache = array_fill(1, $colums, 0);
        $checkpoints = array();
        $keepTrainning = true;

        // Initialize RNA vars
        $this->initialize(count($input[0]) - 1);
        $just_started = true;
        $totalRun = 0;
        $yin = 0;

        // Trains RNA until it gets stable
        while ($keepTrainning == true) {
            // Sweeps each row of the input subject
            foreach ($input as $row_counter => $row_data) {
                // Finds out the number of columns the input has
                $n_columns = count($row_data) - 1;

                // Calculates Yin
                $yin = 0;
                for($i = 1; $i <= $n_columns; $i ++) {
                    $yin += $row_data["x" . $i] * $weightCache[$i];
                }

                // Calculates Real Output
                $Y = ($yin <= 1) ? - 1 : 1;

                // Sweeps columns ...
                $checkpoints[$row_counter] = 0;
                for($i = 1; $i <= $n_columns; $i ++) {
                    /** DELTAS **/
                    // Is it the first row?
                    if ($just_started == true) {
                        $this->dw[$i] = $weightCache[$i];
                        $just_started = false;
                        // Found desired output?
                    } elseif ($Y == $row_data["o"]) {
                        $this->dw[$i] = 0;
                        // Calculates Delta Ws
                    } else {
                        $this->dw[$i] = $row_data["x" . $i] * $row_data["o"];
                    }

                    /** WEIGHTS **/
                    // Calculate Weights
                    $this->w[$i] = $this->dw[$i] + $weightCache[$i];
                    $weightCache[$i] = $this->w[$i];

                    /** CHECK-POINT **/
                    $checkpoints[$row_counter] += $this->w[$i];
                } // END - for

                foreach ($this->w as $index => $w_item) {
                    $debug_w["W" . $index] = $w_item;
                    $debug_dw["deltaW" . $index] = $this->dw[$index];
                }

                // Special for script debugging
                $debug_vars[] = array_merge($row_data, array(
                    "Bias" => 1,
                    "Yin" => $yin,
                    "Y" => $Y
                ), $debug_dw, $debug_w, array(
                    "deltaBias" => 1
                ));
            } // END - foreach

            // Special for script debugging
             $empty_data_row = array();
            for($i = 1; $i <= $n_columns; $i ++) {
                $empty_data_row["x" . $i] = "--";
                $empty_data_row["W" . $i] = "--";
                $empty_data_row["deltaW" . $i] = "--";
            }
            $debug_vars[] = array_merge($empty_data_row, array(
                "o" => "--",
                "Bias" => "--",
                "Yin" => "--",
                "Y" => "--",
                "deltaBias" => "--"
            ));

            // Counts training times
            $totalRun ++;

            // Now checks if the RNA is stable already
            $referer_value = end($checkpoints);
            // if all rows match the desired output ...
            $sum = array_sum($checkpoints);
            $n_rows = count($checkpoints);
            if ($totalRun > 1 && ($sum / $n_rows) == $referer_value) {
                $keepTrainning = false;
            }
        } // END - while

        // Prepares the final result
        $result = array();
        for($i = 1; $i <= $n_columns; $i ++) {
            $result["w" . $i] = $this->w[$i];
        }

        $this->debug($this->print_html_table($debug_vars));

        return $result;
    } // END - train
    function testCase($input, $results) {
        // Sweeps input columns
        $result = 0;
        $i = 1;
        foreach ($input as $column_value) {
            // Calculates teste Y
            $result += $results["w" . $i] * $column_value;
            $i ++;
        }
        // Checks in each class the test fits
        return ($result > 0) ? true : false;
    } // END - test_class

    // Returns the html code of a html table base on a hash array
    function print_html_table($array) {
        $html = "";
        $inner_html = "";
        $table_header_composed = false;
        $table_header = array();

        // Builds table contents
        foreach ($array as $array_item) {
            $inner_html .= "<tr>\n";
            foreach ( $array_item as $array_col_label => $array_col ) {
                $inner_html .= "<td>\n";
                $inner_html .= $array_col;
                $inner_html .= "</td>\n";

                if ($table_header_composed == false) {
                    $table_header[] = $array_col_label;
                }
            }
            $table_header_composed = true;
            $inner_html .= "</tr>\n";
        }

        // Builds full table
        $html = "<table border=1>\n";
        $html .= "<tr>\n";
        foreach ($table_header as $table_header_item) {
            $html .= "<td>\n";
            $html .= "<b>" . $table_header_item . "</b>";
            $html .= "</td>\n";
        }
        $html .= "</tr>\n";

        $html .= $inner_html . "</table>";

        return $html;
    } // END - print_html_table

    // Debug function
    function debug($message) {
        if ($this->debug == true) {
            echo "<b>DEBUG:</b> $message";
        }
    } // END - debug
} // END - class

결론

고유 식별자가없는 사용자를 식별하는 것은 간단하거나 간단한 작업이 아닙니다. 다양한 방법으로 사용자로부터 수집 할 수있는 충분한 양의 임의 데이터를 수집하는 데 달려 있습니다.

인공 신경 네트워크를 사용하지 않더라도 적어도 우선 순위와 가능성을 가진 단순 확률 매트릭스를 사용하는 것이 좋습니다. 위에 제공된 코드와 예제가 충분히 진행되기를 바랍니다.


@Baba "Blobs를 사용하여"브라우저를 지 문화한다는 것은 무엇을 의미합니까?
billmalarky


1
@ 바바 브라우저를 지문으로 사용하는 방법은 무엇입니까? 주어진 시간에 현재 무엇이 들어 있는지 확인하십시오.
billmalarky

@Baba의 훌륭한 작업은 항상 사용자를 식별하기 위해 여러 가지 수준의 전략을 시도했지만 캐시가 지워지거나 IP가 변경되거나 프록시 또는 NAT를 사용하는 사용자, 특히 해당 사용자 -쿠키 삭제 등이 가능합니다. 그러나 많은 노력을 기울여도 악의적 인 사용자가 Tor 브라우저를 사용하는 경우 언급 된 모든 탐지 전략이 작동하지 않는 경우에도 대부분 문제가 될 수 있습니다. 내가 좋아 browserleaks.com 하지만 토르 모든 다시 정의되지 않았거나 알 수없는 온
미 창의력

이 참고 자료의 주옥 에서 "먼지 제거" 만을 목적으로하는 참고 사항 : 07.09.17 현재 부러진 링크 목록 :- Implement Bayesian inference using PHP, 세 부분 모두. - Frequency vs Probability - Joint Probability -Input (Sensor & Desired), Initial Weights, Output (Sensor, Sum, Network), Error, Correction and Final Weights
지치

28

쿠키없이 또는 심지어 IP 주소없이 동일한 사용자를 감지하는이 기술을 브라우저 지문 이라고 합니다 . 기본적으로 브라우저에 대한 정보로 크롤링 할 수 있습니다. javascript, flash 또는 java (f.ex. 설치된 확장 프로그램, 글꼴 등)를 사용하면 더 나은 결과를 얻을 수 있습니다. 그런 다음 원하는 경우 해시 결과를 저장할 수 있습니다.

완벽한 것은 아니지만 :

본 브라우저의 83.6 %는 고유 한 지문을 가지고있었습니다. 플래시 또는 자바를 사용하는 사람들 중 94.2 %. 쿠키는 포함되지 않습니다!

더 많은 정보:


제 생각 엔 여전히 답입니다. 장치를 식별 해야하는 경우 해당 데이터 만 가져와야합니다-f.ex. OS, 일반 확장 (및 그 버전), 설치된 글꼴 등 ...
pozs

이것은 잘 작동하지 않을 것입니다. 모든 브라우저는 세션과 쿠키를 지원합니다. 작업에 적합한 도구를 사용하십시오.
Man Vs Code

1
@ slash197 파일 캐시는 어떻습니까? 나는 쿠키 또는 로그 아웃을 삭제 하더라도이 방법으로 고유 한 생성 된 ID를 보유하고있는 XML 파일과 함께 1px x 1px 투명 플래시 미디어를 사용합니다 (XML은 사용자 로컬 HD로 다운로드되기 전에 서버에서 한 번 작성해야 함). 조치 스크립트 sendAndLoad 메소드를 사용하여 브릿지를 계속 사용할 수 있습니다.
Mbarry

최소 변경은 해시 결과에 영향을 미칩니다. 예를 들어 충격파 플레이어의 버전. 브라우저에서 고유 키 생성 + 숨겨진 1px x 1px 플래시 미디어 (액션 스크립트)를 사용하여 로컬에 저장된 xml 캐시 파일을 사용하여 가능한 해결책은 쿠키를 제거하고 세션 만료 문제가 주요 문제인 경우입니다. 여전히 SQL 데이터베이스와 사용자 로컬 시스템의 키 사이에 브릿지를 가질 수 있습니다.
Mbarry

@Mbarry 나는 플래시 팬이 많지 않지만 브라우저에 1x1 픽셀 플래시 미디어가 비활성화 된 것처럼 플래시 차단 애드온이 있으면 견고합니까?
slash197

7

위에서 언급 한 지문은 작동하지만 여전히 문제가 발생할 수 있습니다.

한 가지 방법은 사용자와의 각 상호 작용 URL에 UID를 추가하는 것입니다.

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

사이트의 모든 링크가이 수정자를 사용하는 경우 ASP.Net이 페이지 간 FORM 데이터를 사용하는 방식과 유사합니다.


나는 그것을 생각했지만 그것이 사용자가 그것을 수정하는 가장 쉬운 방법입니다
slash197

1
ID가 아닌 자체 참조 해시입니다. 암호로 안전하게 만듭니다.
저스틴 알렉산더

또한이 방법은 누군가가 사이트를 탐색 할 때 괜찮지 만 재 방문 사용자가 일주일 후에 다시 방문하여 ID없이 웹 사이트 주소를 입력하면 사건 처리를 어떻게 제안합니까?
slash197

이 경우 @ slash197은 사용자에게 로그인을 요청하지 말고 쿠키를 삭제할 때 발생하는 일을 알려줍니다.
Akash Kava

6

Evercookie 를 살펴 보셨습니까 ? 브라우저에서 작동하거나 작동하지 않을 수 있습니다. 그들의 사이트에서 추출한 것.

"사용자가 한 브라우저에서 쿠키를 받고 다른 브라우저로 전환하면 여전히 로컬 공유 객체 쿠키가있는 한 쿠키는 두 브라우저에서 모두 재생됩니다."


JavaScript가 비활성화 된 상태에서 작동하는지 궁금합니다. 경험이 있습니까?
Voitcus가

이유는 에버 쿠키 (Evercookie)라고 불립니다. 쿠키를 제거하는 것은 거의 불가능합니다.
Alexis Tyler

무슨 일이 있어도 작동하지 않습니다. 설명의 첫 번째 줄에서 : 'evercookie는 자바 스크립트 API입니다 ...'. 자바 스크립트가 비활성화되어 있으면 작동하지 않습니다.
gdw2

js를 비활성화 할 필요도 없습니다. 유령과 uBlock은 evercookie를 떨어 뜨립니다
opengrid

3

캐시 된 png 로이 작업을 수행 할 수는 있지만 다소 신뢰할 수는 없지만 (다른 브라우저는 다르게 동작하며 사용자가 캐시를 지우면 실패합니다) 옵션입니다.

1 : 고유 한 사용자 ID를 16 진 문자열로 저장하는 데이터베이스 설정

2 : 사용자 ID를 생성하고 DB에 저장 한 다음 16 진수 문자열 (각 픽셀은 4 바이트)의 값으로 트루 컬러 .png를 생성하는 genUser.php (또는 다른 언어) 파일을 생성 브라우저로 컨텐츠 유형 및 캐시 헤더를 설정하십시오.

3 : HTML 또는 JS에서 다음과 같은 이미지를 만듭니다. <img id='user_id' src='genUser.php' />

4 : 캔버스에 해당 이미지 그리기 ctx.drawImage(document.getElementById('user_id'), 0, 0);

5 :를 사용하여 해당 이미지의 바이트를 읽고 ctx.getImageData정수를 16 진 문자열로 변환하십시오.

6 : 이제는 사용자 컴퓨터에 캐시 된 고유 한 사용자 ID입니다.


그는 여기서 작동하지 않는 "브라우저 간"사용자를 추적 할 수있는 것을 원합니다 (각 브라우저마다 고유 한 캐시 데이터베이스가 있음).
EricLaw

어디에서 보았는지, 그의 질문은 "브라우저와 호환 가능해야한다는 것을 잊어 버렸습니다."
hobberwickey 2016 년

그의 질문은 잘못 쓰여졌다. I'm after device recognition그가 원하는 것에 대한 경품이며, 여기에서 자세히 설명합니다 : stackoverflow.com/questions/15966812/…
EricLaw

2

당신이 말한 것을 바탕으로 :

기본적으로 나는 사용자가 아닌 장치 인식 후

가장 좋은 방법은 NIC ID 인 mac 주소를 보내는 것입니다.

이 게시물을 살펴볼 수 있습니다 : PHP로 연결된 클라이언트의 MAC 및 IP 주소를 얻는 방법은 무엇입니까?


죄송하지만 NIC ID는 스푸핑하기 쉽습니다. 확실히 최선의 방법은 아닙니다.
ass

@asgs 브라우저 지문이 더 좋을 수도 있고 의견에 가장 좋은 방법은 무엇입니까?
Mehdi Karamosly

가장 좋은 방법은 없습니다. 그것이 슬픈 부분입니다. 그러나 Baba가 제시 한 확률 연구와 함께 브라우저 핑거 프린팅과 브라우저 핑거 프린팅이 제 의견으로는 최고라고 생각합니다.
ass

1

etags로 할 수 있습니다. 이 소송이 다수의 소송으로 제기되었는지는 확실하지 않습니다.

사용자에게 올바르게 경고하거나 인트라넷 웹 사이트와 같은 것이 있으면 정상일 수 있습니다.


전자 태그는 브라우저 간 호환되지 않습니다.
slash197

1
태그는 HTTP / 1.1 사양의 일부입니다. 모든 인기있는 브라우저는 etag를 지원하므로 ETag / If-None-Match 헤더를 지원하지 않으려면 자체 브라우저를 작성해야합니다.
Brian McGinity

나는 그것을 지원하지 않는다고 말하지 않았으며, 크로스 브라우저와 호환되지 않는다고 말했다. 태그가 Firefox에 저장된 경우 크롬에서 사용할 수 없으므로 캐시가 없으므로 컨텐츠가 다시 다운로드됩니다.
slash197

나는 당신이 무슨 말을했는지 이해합니다. 네가 옳아. 각 브라우저에는 자체 캐시 저장소가 있으므로 다른 etag가 있습니다.
Brian McGinity


0

비효율적이지만 원하는 결과를 얻을 수 있다면 API를 폴링하는 것입니다. 클라이언트 측에서 백그라운드 프로세스를 통해 간격을두고 사용자 데이터를 보냅니다. API로 보내려면 사용자 식별자가 필요합니다. 일단 당신이 그 고유 식별자와 관련된 정보를 함께 보낼 수 있습니다.

쿠키와 로컬 스토리지가 필요하지 않습니다.


0

믿을 수 없습니다, http://browserspy.dk는 아직 여기에 언급되지 않았습니다! 이 사이트는 분류기를 구축하는 데 사용할 수있는 많은 기능 (패턴 인식 측면에서)을 설명합니다.

그리고 기능의 평가를 위해 특히 Support Vector Machines 및 libsvm 을 제안 합니다.


0

한 세션 동안 또는 여러 세션에서 추적합니까?

사이트가 HTTPS Everywhere 인 경우 TLS 세션 ID를 사용하여 사용자 세션을 추적 할 수 있습니다.


1
여기서 질문은 어떻게?
user455318

-2
  1. 크로스 플랫폼 더미 (nsapi) 플러그인을 생성하고 사용자가 다운로드 할 때 (예 : 로그인 후) 플러그인 이름 또는 버전의 고유 이름을 생성합니다.
  2. 플러그인 설치 프로그램 제공 / 정책에 따라 설치

이를 위해서는 사용자가 기꺼이 식별자를 설치해야합니다.

플러그인이 설치되면 (플러그인 가능) 브라우저 지문 에이 특정 플러그인이 포함됩니다. 정보를 서버로 반환하려면 클라이언트 측에서 플러그인을 효과적으로 감지하는 알고리즘이 필요합니다. 그렇지 않으면 IE 및 Firefox> = 28 사용자는 가능한 유효한 식별 테이블이 필요합니다.

이를 위해서는 브라우저 공급 업체에 의해 종료 될 수있는 기술에 상대적으로 많은 투자가 필요합니다. 사용자가 플러그인을 설치하도록 설득 할 수있는 경우 설치와 같은 옵션이있을 수 있습니다. 로컬 프록시 , vpn 사용 또는 네트워크 드라이버 패치 .

식별되기를 원하지 않는 사용자 (또는 시스템)는 항상이를 방지 할 방법을 찾습니다.


스택 오버플로에 오신 것을 환영합니다. 참고하십시오; this will require the user to willingly install the identifier.아마도 원래 포스터 (OP)의 의미가 아닐 수도 있습니다.
Stefan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.