126 lines
4.9 KiB
Python
126 lines
4.9 KiB
Python
"""
|
|
检查前端实际发送的签名头
|
|
"""
|
|
|
|
from playwright.sync_api import sync_playwright
|
|
import time
|
|
|
|
def check_frontend_signature():
|
|
"""检查前端签名头"""
|
|
with sync_playwright() as p:
|
|
browser = p.chromium.launch(headless=True)
|
|
context = browser.new_context()
|
|
page = context.new_page()
|
|
|
|
signature_headers = {}
|
|
|
|
def handle_request(request):
|
|
if '/api/users/page' in request.url:
|
|
signature_headers['url'] = request.url
|
|
signature_headers['method'] = request.method
|
|
signature_headers['X-Signature'] = request.headers.get('X-Signature', 'None')
|
|
signature_headers['X-Timestamp'] = request.headers.get('X-Timestamp', 'None')
|
|
signature_headers['X-Nonce'] = request.headers.get('X-Nonce', 'None')
|
|
|
|
print(f"\n捕获到用户列表请求:")
|
|
print(f" URL: {request.url}")
|
|
print(f" Method: {request.method}")
|
|
print(f" X-Signature: {signature_headers['X-Signature'][:30] if signature_headers['X-Signature'] != 'None' else 'None'}...")
|
|
print(f" X-Timestamp: {signature_headers['X-Timestamp']}")
|
|
print(f" X-Nonce: {signature_headers['X-Nonce']}")
|
|
|
|
page.on('request', handle_request)
|
|
|
|
try:
|
|
print("=" * 60)
|
|
print("检查前端签名头")
|
|
print("=" * 60)
|
|
|
|
print("\n1. 登录...")
|
|
page.goto('http://localhost:3002/login')
|
|
page.wait_for_load_state('networkidle')
|
|
page.fill('input[type="text"], input[placeholder*="用户名"]', 'admin')
|
|
page.fill('input[type="password"]', 'admin123')
|
|
|
|
with page.expect_navigation(timeout=10000):
|
|
page.click('button:has-text("登录")')
|
|
|
|
time.sleep(2)
|
|
|
|
print("\n2. 访问用户管理页面...")
|
|
page.goto('http://localhost:3002/users')
|
|
time.sleep(5)
|
|
page.wait_for_load_state('networkidle')
|
|
|
|
if signature_headers:
|
|
print("\n" + "=" * 60)
|
|
print("前端签名头信息:")
|
|
print("=" * 60)
|
|
|
|
url = signature_headers.get('url', '')
|
|
method = signature_headers.get('method', 'GET')
|
|
signature = signature_headers.get('X-Signature', 'None')
|
|
timestamp = signature_headers.get('X-Timestamp', 'None')
|
|
nonce = signature_headers.get('X-Nonce', 'None')
|
|
|
|
print(f"URL: {url}")
|
|
print(f"Method: {method}")
|
|
print(f"X-Signature: {signature}")
|
|
print(f"X-Timestamp: {timestamp}")
|
|
print(f"X-Nonce: {nonce}")
|
|
|
|
# 手动验证签名
|
|
if timestamp != 'None' and nonce != 'None':
|
|
from urllib.parse import urlparse, parse_qs
|
|
|
|
parsed = urlparse(url)
|
|
path = parsed.path
|
|
query = parsed.query
|
|
|
|
print(f"\n路径: {path}")
|
|
print(f"查询参数: {query}")
|
|
|
|
# 生成期望的签名
|
|
import hmac
|
|
import hashlib
|
|
import base64
|
|
|
|
secret = 'NovalonManageSystemSecretKey2026'
|
|
string_to_sign = '\n'.join([
|
|
method,
|
|
path,
|
|
query or '',
|
|
'',
|
|
timestamp,
|
|
nonce
|
|
])
|
|
|
|
expected_signature = base64.b64encode(
|
|
hmac.new(
|
|
secret.encode('utf-8'),
|
|
string_to_sign.encode('utf-8'),
|
|
hashlib.sha256
|
|
).digest()
|
|
).decode('utf-8')
|
|
|
|
print(f"\n期望的签名: {expected_signature}")
|
|
print(f"实际的签名: {signature}")
|
|
|
|
if signature == expected_signature:
|
|
print("\n✅ 签名匹配")
|
|
else:
|
|
print("\n❌ 签名不匹配")
|
|
print(f"\n签名字符串:\n{string_to_sign}")
|
|
else:
|
|
print("\n❌ 未捕获到用户列表请求")
|
|
|
|
except Exception as e:
|
|
print(f"\n❌ 错误: {str(e)}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
finally:
|
|
browser.close()
|
|
|
|
if __name__ == "__main__":
|
|
check_frontend_signature()
|