136 lines
5.2 KiB
Python
136 lines
5.2 KiB
Python
# modules/fingerprint.py
|
||
"""浏览器指纹生成器"""
|
||
|
||
import uuid
|
||
import random
|
||
import time
|
||
from datetime import datetime
|
||
from typing import Dict, List, Any
|
||
|
||
from config import FINGERPRINT_CONFIG
|
||
|
||
|
||
class BrowserFingerprint:
|
||
"""生成符合 SDK 期望的浏览器指纹"""
|
||
|
||
def __init__(self, session_id: str = None):
|
||
self.session_id = session_id or str(uuid.uuid4())
|
||
self.user_agent = FINGERPRINT_CONFIG['user_agent']
|
||
self.screen_width = FINGERPRINT_CONFIG['screen_width']
|
||
self.screen_height = FINGERPRINT_CONFIG['screen_height']
|
||
self.languages = FINGERPRINT_CONFIG['languages']
|
||
self.hardware_concurrency = FINGERPRINT_CONFIG['hardware_concurrency']
|
||
|
||
def get_config_array(self) -> List[Any]:
|
||
"""
|
||
生成 SDK getConfig() 函数返回的 18 元素数组
|
||
|
||
对应 SDK 源码:
|
||
[0]: screen.width + screen.height
|
||
[1]: new Date().toString()
|
||
[2]: performance.memory.jsHeapSizeLimit (可选)
|
||
[3]: nonce (PoW 填充)
|
||
[4]: navigator.userAgent
|
||
[5]: 随机 script.src
|
||
[6]: build ID
|
||
[7]: navigator.language
|
||
[8]: navigator.languages.join(',')
|
||
[9]: 运行时间 (PoW 填充)
|
||
[10]: 随机 navigator 属性
|
||
[11]: 随机 document key
|
||
[12]: 随机 window key
|
||
[13]: performance.now()
|
||
[14]: session UUID
|
||
[15]: URL search params
|
||
[16]: navigator.hardwareConcurrency
|
||
[17]: performance.timeOrigin
|
||
"""
|
||
|
||
# 模拟的 script sources
|
||
fake_scripts = [
|
||
"https://sentinel.openai.com/sentinel/97790f37/sdk.js",
|
||
"https://chatgpt.com/static/js/main.abc123.js",
|
||
"https://cdn.oaistatic.com/_next/static/chunks/main.js",
|
||
]
|
||
|
||
# 模拟的 navigator 属性名
|
||
navigator_props = [
|
||
'hardwareConcurrency', 'language', 'languages',
|
||
'platform', 'userAgent', 'vendor'
|
||
]
|
||
|
||
# 模拟的 document keys
|
||
document_keys = ['body', 'head', 'documentElement', 'scripts']
|
||
|
||
# 模拟的 window keys
|
||
window_keys = ['performance', 'navigator', 'document', 'location']
|
||
|
||
current_time = time.time() * 1000
|
||
|
||
return [
|
||
self.screen_width + self.screen_height, # [0]
|
||
str(datetime.now()), # [1]
|
||
None, # [2] memory
|
||
None, # [3] nonce (placeholder)
|
||
self.user_agent, # [4]
|
||
random.choice(fake_scripts), # [5]
|
||
"97790f37", # [6] build ID
|
||
self.languages[0], # [7]
|
||
",".join(self.languages), # [8]
|
||
None, # [9] runtime (placeholder)
|
||
f"{random.choice(navigator_props)}−{random.randint(1, 16)}", # [10]
|
||
random.choice(document_keys), # [11]
|
||
random.choice(window_keys), # [12]
|
||
current_time, # [13]
|
||
self.session_id, # [14]
|
||
"", # [15] URL params
|
||
self.hardware_concurrency, # [16]
|
||
current_time - random.uniform(100, 1000), # [17] timeOrigin
|
||
]
|
||
|
||
def get_cookies(self) -> Dict[str, str]:
|
||
"""生成初始 cookies"""
|
||
return {
|
||
'oai-did': self.session_id,
|
||
}
|
||
|
||
def get_headers(self, with_sentinel: str = None) -> Dict[str, str]:
|
||
"""生成 HTTP headers"""
|
||
|
||
# 基础 headers
|
||
headers = {
|
||
'User-Agent': self.user_agent,
|
||
'Accept': 'application/json',
|
||
'Accept-Language': f"{self.languages[0]},{self.languages[1]};q=0.5",
|
||
'Accept-Encoding': 'gzip, deflate, br, zstd',
|
||
'Referer': 'https://auth.openai.com/create-account/password',
|
||
'Content-Type': 'application/json',
|
||
'Origin': 'https://auth.openai.com',
|
||
'Connection': 'keep-alive',
|
||
'Sec-Fetch-Dest': 'empty',
|
||
'Sec-Fetch-Mode': 'cors',
|
||
'Sec-Fetch-Site': 'same-origin',
|
||
'Priority': 'u=4',
|
||
'Pragma': 'no-cache',
|
||
'Cache-Control': 'no-cache',
|
||
}
|
||
|
||
# Sentinel token
|
||
if with_sentinel:
|
||
headers['openai-sentinel-token'] = with_sentinel
|
||
|
||
# Datadog RUM tracing (OpenAI 使用)
|
||
trace_id = random.randint(10**18, 10**19 - 1)
|
||
parent_id = random.randint(10**18, 10**19 - 1)
|
||
|
||
headers.update({
|
||
'traceparent': f'00-0000000000000000{trace_id:016x}-{parent_id:016x}-01',
|
||
'tracestate': 'dd=s:1;o:rum',
|
||
'x-datadog-origin': 'rum',
|
||
'x-datadog-parent-id': str(parent_id),
|
||
'x-datadog-sampling-priority': '1',
|
||
'x-datadog-trace-id': str(trace_id),
|
||
})
|
||
|
||
return headers
|