@adstage/web-sdk 2.4.12 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,191 +0,0 @@
1
- /**
2
- * BasicFraudDetector - 현실적 구현 버전
3
- * 기본적인 봇 탐지 및 간단한 행동 패턴 분석
4
- */
5
-
6
- export interface FraudScore {
7
- score: number; // 0-100
8
- riskLevel: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
9
- reasons: string[];
10
- }
11
-
12
- export interface BasicBrowserInfo {
13
- userAgent: string;
14
- language: string;
15
- platform: string;
16
- cookieEnabled: boolean;
17
- doNotTrack: string | null;
18
- timezone: string;
19
- screenResolution: string;
20
- viewportSize: string;
21
- }
22
-
23
- export class BasicFraudDetector {
24
- private startTime: number;
25
- private mouseEvents: number = 0;
26
- private keyboardEvents: number = 0;
27
- private scrollEvents: number = 0;
28
-
29
- constructor() {
30
- this.startTime = Date.now();
31
- this.initBasicTracking();
32
- }
33
-
34
- private initBasicTracking(): void {
35
- // 기본적인 사용자 상호작용 추적
36
- document.addEventListener('mousemove', () => this.mouseEvents++, { passive: true });
37
- document.addEventListener('keydown', () => this.keyboardEvents++, { passive: true });
38
- document.addEventListener('scroll', () => this.scrollEvents++, { passive: true });
39
- }
40
-
41
- public calculateFraudScore(): FraudScore {
42
- let score = 0;
43
- const reasons: string[] = [];
44
-
45
- // 1. 웹드라이버 탐지 (기본)
46
- if (this.detectWebDriver()) {
47
- score += 50;
48
- reasons.push('WebDriver detected');
49
- }
50
-
51
- // 2. 헤드리스 브라우저 기본 탐지
52
- if (this.detectBasicHeadless()) {
53
- score += 40;
54
- reasons.push('Headless browser signatures');
55
- }
56
-
57
- // 3. 사용자 상호작용 부족
58
- const sessionTime = Date.now() - this.startTime;
59
- if (sessionTime > 5000) { // 5초 이상 경과
60
- if (this.mouseEvents === 0) {
61
- score += 20;
62
- reasons.push('No mouse interaction');
63
- }
64
-
65
- if (this.scrollEvents === 0 && sessionTime > 10000) {
66
- score += 15;
67
- reasons.push('No scroll activity');
68
- }
69
- }
70
-
71
- // 4. 브라우저 환경 이상 징후
72
- const browserCheck = this.checkBrowserEnvironment();
73
- score += browserCheck.score;
74
- reasons.push(...browserCheck.reasons);
75
-
76
- // 5. 시간 패턴 이상 (너무 빠른 페이지 로드 후 즉시 클릭)
77
- if (sessionTime < 1000) {
78
- score += 25;
79
- reasons.push('Suspiciously fast interaction');
80
- }
81
-
82
- const finalScore = Math.min(score, 100);
83
-
84
- return {
85
- score: finalScore,
86
- riskLevel: this.getRiskLevel(finalScore),
87
- reasons: reasons
88
- };
89
- }
90
-
91
- private detectWebDriver(): boolean {
92
- // 기본적인 웹드라이버 탐지
93
- return !!(
94
- (window as any).webdriver ||
95
- (navigator as any).webdriver ||
96
- (window as any).__webdriver_evaluate ||
97
- (window as any).__selenium_evaluate ||
98
- (window as any).__webdriver_script_function ||
99
- (window as any).__webdriver_script_func ||
100
- (window as any).__webdriver_script_fn ||
101
- (window as any).__fxdriver_evaluate ||
102
- (window as any).__driver_unwrapped ||
103
- (window as any).__webdriver_unwrapped ||
104
- (window as any).__driver_evaluate ||
105
- (window as any).__selenium_unwrapped ||
106
- (window as any).__fxdriver_unwrapped
107
- );
108
- }
109
-
110
- private detectBasicHeadless(): boolean {
111
- const signatures: string[] = [];
112
-
113
- // PhantomJS 탐지
114
- if ((window as any)._phantom || (window as any).phantom) {
115
- signatures.push('PhantomJS');
116
- }
117
-
118
- // Chrome headless 기본 탐지
119
- if (navigator.userAgent.includes('HeadlessChrome')) {
120
- signatures.push('Chrome Headless');
121
- }
122
-
123
- // 플러그인 없음 (일반적이지 않음)
124
- if (navigator.plugins.length === 0) {
125
- signatures.push('No plugins');
126
- }
127
-
128
- return signatures.length > 0;
129
- }
130
-
131
- private checkBrowserEnvironment(): { score: number; reasons: string[] } {
132
- let score = 0;
133
- const reasons: string[] = [];
134
-
135
- // 언어 설정 이상
136
- if (!navigator.language || navigator.language === 'C') {
137
- score += 10;
138
- reasons.push('Unusual language setting');
139
- }
140
-
141
- // 쿠키 비활성화
142
- if (!navigator.cookieEnabled) {
143
- score += 15;
144
- reasons.push('Cookies disabled');
145
- }
146
-
147
- // 화면 해상도 이상
148
- if (screen.width === 0 || screen.height === 0) {
149
- score += 20;
150
- reasons.push('Invalid screen resolution');
151
- }
152
-
153
- // 시간대 정보 없음
154
- try {
155
- const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
156
- if (!timezone || timezone === 'UTC') {
157
- score += 5;
158
- reasons.push('No timezone info');
159
- }
160
- } catch (e) {
161
- score += 10;
162
- reasons.push('Timezone detection failed');
163
- }
164
-
165
- return { score, reasons };
166
- }
167
-
168
- private getRiskLevel(score: number): 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL' {
169
- if (score >= 70) return 'CRITICAL';
170
- if (score >= 50) return 'HIGH';
171
- if (score >= 30) return 'MEDIUM';
172
- return 'LOW';
173
- }
174
-
175
- public getBrowserInfo(): BasicBrowserInfo {
176
- return {
177
- userAgent: navigator.userAgent,
178
- language: navigator.language,
179
- platform: navigator.platform,
180
- cookieEnabled: navigator.cookieEnabled,
181
- doNotTrack: navigator.doNotTrack,
182
- timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
183
- screenResolution: `${screen.width}x${screen.height}`,
184
- viewportSize: `${window.innerWidth}x${window.innerHeight}`
185
- };
186
- }
187
-
188
- public destroy(): void {
189
- // 이벤트 리스너 정리는 생략 (메모리 누수 방지를 위해 필요시 구현)
190
- }
191
- }