Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import time
- import json
- import random
- import string
- import requests
- import threading
- import argparse
- import webbrowser
- import hashlib
- import base64
- import secrets
- from datetime import datetime
- # 生成随机字符串的函数
- def generate_random_string(length=32):
- """生成指定长度的随机字符串,用于challenge和uuid参数"""
- chars = string.ascii_letters + string.digits + '-_'
- return ''.join(random.choice(chars) for _ in range(length))
- # 生成UUID格式的函数
- def generate_uuid():
- """生成uuid格式的随机字符串"""
- parts = [
- generate_random_string(8),
- generate_random_string(4),
- generate_random_string(4),
- generate_random_string(4),
- generate_random_string(12)
- ]
- return '-'.join(parts)
- # 生成challenge参数的函数
- def generate_challenge():
- """生成challenge参数"""
- return generate_random_string(24)
- # 生成PKCE验证器和挑战码对
- def generate_pkce_pair():
- """生成PKCE验证器和挑战码对,用于OAuth 2.0 PKCE流程"""
- # 生成一个安全的随机码作为验证器
- code_verifier = secrets.token_urlsafe(43) # 43字符长度会产生一个足够长的verifier
- # 计算挑战码 (code_challenge)
- code_challenge_digest = hashlib.sha256(code_verifier.encode('utf-8')).digest()
- code_challenge = base64.urlsafe_b64encode(code_challenge_digest).decode('utf-8').rstrip('=')
- return code_verifier, code_challenge
- # 轮询API获取cookie的函数
- def poll_for_cookie(uuid, verifier, stop_event):
- """持续轮询API获取cookie,直到获取成功或手动停止"""
- api_url = f"https://api2.cursor.sh/auth/poll?uuid={uuid}&verifier={verifier}"
- traceparent = f"00-{generate_random_string(32)}-{generate_random_string(16)}-00"
- # OPTIONS预检请求的头部
- headers_options = {
- "Host": "api2.cursor.sh",
- "Connection": "keep-alive",
- "Accept": "*/*",
- "Access-Control-Request-Method": "GET",
- "Access-Control-Request-Headers": "traceparent,x-ghost-mode,x-new-onboarding-completed",
- "Origin": "vscode-file://vscode-app",
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Cursor/0.48.6 Chrome/132.0.6834.210 Electron/34.3.4 Safari/537.36",
- "Sec-Fetch-Mode": "cors",
- "Sec-Fetch-Site": "cross-site",
- "Sec-Fetch-Dest": "empty",
- "Accept-Language": "zh-CN"
- }
- # GET请求的头部
- headers_get = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Cursor/0.48.6 Chrome/132.0.6834.210 Electron/34.3.4 Safari/537.36",
- "Accept": "*/*",
- "Origin": "vscode-file://vscode-app",
- "Sec-Fetch-Site": "cross-site",
- "Sec-Fetch-Mode": "cors",
- "Sec-Fetch-Dest": "empty",
- "traceparent": traceparent,
- "sec-ch-ua-platform": "Windows",
- "x-ghost-mode": "true",
- "x-new-onboarding-completed": "false",
- "sec-ch-ua": "\"Not A(Brand\";v=\"8\", \"Chromium\";v=\"132\"",
- "sec-ch-ua-mobile": "?0",
- "Accept-Language": "zh-CN",
- "Connection": "keep-alive"
- }
- attempt = 0
- print("开始轮询API获取cookie...")
- print(f"请求接口:{api_url}")
- while not stop_event.is_set():
- attempt += 1
- try:
- print(f"尝试 #{attempt}...")
- # 先发送OPTIONS预检请求
- print(f"发送OPTIONS预检请求...")
- options_response = requests.options(api_url, headers=headers_options, timeout=5)
- print(f"OPTIONS预检响应状态码: {options_response.status_code}")
- # 等待一小段时间再发送GET请求
- time.sleep(0.2)
- # 发送GET请求获取cookie
- response = requests.get(api_url, headers=headers_get, timeout=5)
- if response.status_code == 200:
- data = response.json()
- print(f"API响应: {data}")
- if 'accessToken' in data:
- token = data['accessToken']
- print("\n============ 成功获取Cookie! ============")
- print(f"Token: {token}")
- # 将token保存到文件
- current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
- with open(f"token_{current_time}.txt", "w") as f:
- f.write(token)
- print(f"Token已保存到文件: token_{current_time}.txt")
- print("=======================================\n")
- return token
- else:
- print(f"尝试 #{attempt}: 请求失败,状态码: {response.status_code}")
- except requests.exceptions.Timeout:
- print(f"尝试 #{attempt}: 请求超时")
- except Exception as e:
- print(f"尝试 #{attempt}: 异常 - {e}")
- time.sleep(1) # 每秒轮询一次
- print("轮询已停止")
- return None
- def main():
- parser = argparse.ArgumentParser(description='Cursor Cookie获取测试脚本')
- parser.add_argument('--no-browser', action='store_true', help='不自动打开浏览器')
- parser.add_argument('--uuid', type=str, help='使用指定的UUID,而不是生成随机UUID')
- parser.add_argument('--url', type=str, help='使用指定的完整确认页面URL,而不是生成新URL')
- args = parser.parse_args()
- # 判断是否使用预设的URL
- if args.url:
- # 从URL中解析UUID和challenge
- import re
- url_match = re.search(r'uuid=([^&]+)', args.url)
- uuid = url_match.group(1) if url_match else generate_uuid()
- confirm_url = args.url
- # 生成新的验证器
- verifier, _ = generate_pkce_pair()
- else:
- # 使用命令行参数或生成新的参数
- uuid = args.uuid if args.uuid else generate_uuid()
- # 使用PKCE生成验证器和挑战码
- verifier, challenge = generate_pkce_pair()
- # 生成确认页面URL
- confirm_url = f"https://www.cursor.com/cn/loginDeepControl?challenge={challenge}&uuid={uuid}&mode=login"
- print("\n===== Cursor Cookie获取测试脚本 =====")
- print("此脚本会生成一个确认页面URL,并在后台不断轮询API尝试获取cookie")
- print("请按照以下步骤操作:")
- print("1. 打开确认页面URL")
- print("2. 如果需要登录,请先登录")
- print("3. 在确认页面点击 'Yes, Log In' 按钮")
- print("4. 脚本将自动检测并获取cookie")
- print("5. 按Ctrl+C可随时停止脚本")
- print("====================================\n")
- print(f"确认页面URL: {confirm_url}")
- print(f"使用的UUID: {uuid}")
- print(f"使用的verifier: {verifier}")
- # 如果不禁用浏览器,则自动打开URL
- if not args.no_browser:
- print("正在打开浏览器...")
- webbrowser.open(confirm_url)
- # 创建停止事件
- stop_event = threading.Event()
- try:
- # 在主线程中轮询
- poll_for_cookie(uuid, verifier, stop_event)
- except KeyboardInterrupt:
- print("\n用户中断,正在停止...")
- stop_event.set()
- if __name__ == "__main__":
- main()
Add Comment
Please, Sign In to add comment