feat: 统一JWT密钥配置并修复签名验证问题
修复前端签名生成中bodyString硬编码问题 添加start-frontend.sh脚本启动前端服务 统一manage-app和gateway的JWT密钥配置 修复Repository扫描路径问题 更新测试配置和依赖 重构表名映射为sys_user和sys_role 完善用户实体类字段映射 添加集成测试配置和测试用例
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
"""
|
||||
检查前端实际发送的签名头
|
||||
"""
|
||||
|
||||
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()
|
||||
Reference in New Issue
Block a user