huace-aigc-auth-client 1.1.5__tar.gz → 1.1.7__tar.gz

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.
Files changed (16) hide show
  1. {huace_aigc_auth_client-1.1.5/huace_aigc_auth_client.egg-info → huace_aigc_auth_client-1.1.7}/PKG-INFO +132 -17
  2. {huace_aigc_auth_client-1.1.5 → huace_aigc_auth_client-1.1.7}/README.md +131 -16
  3. {huace_aigc_auth_client-1.1.5 → huace_aigc_auth_client-1.1.7}/huace_aigc_auth_client/__init__.py +1 -1
  4. {huace_aigc_auth_client-1.1.5 → huace_aigc_auth_client-1.1.7}/huace_aigc_auth_client/legacy_adapter.py +5 -2
  5. {huace_aigc_auth_client-1.1.5 → huace_aigc_auth_client-1.1.7}/huace_aigc_auth_client/sdk.py +8 -1
  6. {huace_aigc_auth_client-1.1.5 → huace_aigc_auth_client-1.1.7/huace_aigc_auth_client.egg-info}/PKG-INFO +132 -17
  7. {huace_aigc_auth_client-1.1.5 → huace_aigc_auth_client-1.1.7}/pyproject.toml +1 -1
  8. {huace_aigc_auth_client-1.1.5 → huace_aigc_auth_client-1.1.7}/LICENSE +0 -0
  9. {huace_aigc_auth_client-1.1.5 → huace_aigc_auth_client-1.1.7}/MANIFEST.in +0 -0
  10. {huace_aigc_auth_client-1.1.5 → huace_aigc_auth_client-1.1.7}/QUICK_START.txt +0 -0
  11. {huace_aigc_auth_client-1.1.5 → huace_aigc_auth_client-1.1.7}/huace_aigc_auth_client/webhook.py +0 -0
  12. {huace_aigc_auth_client-1.1.5 → huace_aigc_auth_client-1.1.7}/huace_aigc_auth_client.egg-info/SOURCES.txt +0 -0
  13. {huace_aigc_auth_client-1.1.5 → huace_aigc_auth_client-1.1.7}/huace_aigc_auth_client.egg-info/dependency_links.txt +0 -0
  14. {huace_aigc_auth_client-1.1.5 → huace_aigc_auth_client-1.1.7}/huace_aigc_auth_client.egg-info/requires.txt +0 -0
  15. {huace_aigc_auth_client-1.1.5 → huace_aigc_auth_client-1.1.7}/huace_aigc_auth_client.egg-info/top_level.txt +0 -0
  16. {huace_aigc_auth_client-1.1.5 → huace_aigc_auth_client-1.1.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: huace-aigc-auth-client
3
- Version: 1.1.5
3
+ Version: 1.1.7
4
4
  Summary: 华策AIGC Auth Client - 提供 Token 验证、用户信息获取、权限检查、旧系统接入等功能
5
5
  Author-email: Huace <support@huace.com>
6
6
  License: MIT
@@ -45,7 +45,7 @@ pip install huace-aigc-auth-client
45
45
  AIGC_AUTH_APP_ID=your_app_id
46
46
  AIGC_AUTH_APP_SECRET=your_app_secret
47
47
 
48
- # 可选:鉴权服务地址(默认为生产环境)
48
+ # 可选:鉴权服务地址(默认为生产环境)- 测试环境鉴权地址:https://auth-test.aigc.huacemedia.com/aigc-auth/api/v1
49
49
  AIGC_AUTH_BASE_URL=https://aigc-auth.huacemedia.com/aigc-auth/api/v1
50
50
  ```
51
51
 
@@ -328,21 +328,21 @@ except AigcAuthError as e:
328
328
 
329
329
  ```
330
330
  ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
331
- │ aigc-auth │────▶│ SDK 同步层 │────▶│ 旧系统
332
- │ (鉴权中心) │ │ (字段映射) │ │ (用户表)
331
+ │ aigc-auth │────▶│ SDK 同步层 │────▶│ 旧系统
332
+ │ (鉴权中心) │ │ (字段映射) │ │ (用户表)
333
333
  └─────────────────┘ └─────────────────┘ └─────────────────┘
334
334
  │ │ │
335
- │ 1. 初始化同步 │ │
335
+ │ 1. 初始化同步 │ │
336
336
  │◀──────────────────────────────────────────────│
337
- │ (批量同步旧用户到 auth)
337
+ │ (批量同步旧用户到 auth)
338
338
  │ │ │
339
- │ 2. 增量同步 │ │
339
+ │ 2. 增量同步 │ │
340
340
  │──────────────────────▶│──────────────────────▶│
341
- │ (auth 新用户自动同步到旧系统)
341
+ │ (auth 新用户自动同步到旧系统)
342
342
  │ │ │
343
- │ 3. Webhook 推送 │ │
343
+ │ 3. Webhook 推送 │ │
344
344
  │──────────────────────────────────────────────▶│
345
- │ (用户变更主动通知)
345
+ │ (用户变更主动通知)
346
346
  ```
347
347
 
348
348
  ### 快速开始
@@ -357,7 +357,7 @@ AIGC_AUTH_BASE_URL=https://aigc-auth.huacemedia.com/aigc-auth/api/v1
357
357
 
358
358
  # 同步配置
359
359
  AIGC_AUTH_SYNC_ENABLED=true
360
- AIGC_AUTH_SYNC_PASSWORD=Abc@123456
360
+ AIGC_AUTH_SYNC_PASSWORD=通用密码
361
361
  AIGC_AUTH_WEBHOOK_URL=https://your-domain.com/api/v1/webhook/auth
362
362
  AIGC_AUTH_WEBHOOK_SECRET=your_secret
363
363
  ```
@@ -407,7 +407,7 @@ field_mappings = [
407
407
  sync_config = create_sync_config(
408
408
  field_mappings=field_mappings,
409
409
  password_mode=PasswordMode.UNIFIED,
410
- unified_password="Abc@123456",
410
+ unified_password="通用密码",
411
411
  webhook_url="https://your-domain.com/api/v1/webhook/auth",
412
412
  )
413
413
  ```
@@ -486,18 +486,94 @@ async def auth_middleware(request, call_next):
486
486
 
487
487
  #### 5. 添加 Webhook 接收端点
488
488
 
489
+ **推荐方式:使用 SDK 提供的通用 Webhook 路由**
490
+
489
491
  ```python
492
+ from fastapi import APIRouter
493
+ from huace_aigc_auth_client import register_webhook_router
494
+
495
+ api_router = APIRouter()
496
+
497
+ # 定义 webhook 处理函数
498
+ async def handle_webhook(data: dict) -> dict:
499
+ """
500
+ 处理来自 aigc-auth 的 webhook 通知
501
+
502
+ Args:
503
+ data: webhook 数据,包含 event 和 data 字段
504
+
505
+ Returns:
506
+ dict: 处理结果
507
+ """
508
+ from your_app.db import get_db_session
509
+
510
+ event = data.get("event")
511
+ user_data = data.get("data", {})
512
+
513
+ # 创建数据库会话
514
+ async with get_db_session() as db:
515
+ adapter = MyLegacyAdapter(db, sync_config)
516
+
517
+ if event == "user.created":
518
+ # 处理用户创建事件
519
+ if not adapter.get_user_by_unique_field(user_data["username"]):
520
+ legacy_data = adapter.transform_auth_to_legacy(user_data)
521
+ legacy_data["password"] = sync_config.unified_password
522
+ adapter.create_user(legacy_data)
523
+ await db.commit()
524
+
525
+ elif event == "user.updated":
526
+ # 处理用户更新事件
527
+ legacy_data = adapter.transform_auth_to_legacy(user_data)
528
+ adapter.update_user(user_data["username"], legacy_data)
529
+ await db.commit()
530
+
531
+ return {"status": "ok", "event": event}
532
+
533
+ # 注册 webhook 路由(自动处理签名验证)
534
+ register_webhook_router(
535
+ api_router,
536
+ handler=handle_webhook,
537
+ prefix="/webhook", # 可选,默认 "/webhook"
538
+ secret_env_key="aigc-auth-webhook-secret", # 可选,在 auth 后台配置
539
+ tags=["Webhook"] # 可选,默认 ["Webhook"]
540
+ )
541
+
542
+ # webhook 端点将自动创建在: /webhook/auth
543
+ ```
544
+
545
+ **传统方式:手动实现 Webhook 端点**
546
+
547
+ ```python
548
+ import hmac
549
+ import hashlib
550
+ import os
551
+
490
552
  @app.post("/api/v1/webhook/auth")
491
553
  async def receive_auth_webhook(request: Request, db: Session = Depends(get_db)):
492
554
  """接收 aigc-auth 的用户变更通知"""
555
+ # 获取原始请求体
556
+ body = await request.body()
557
+
558
+ # 验证签名
559
+ signature = request.headers.get("X-Webhook-Signature", "")
560
+ secret = os.getenv("AIGC_AUTH_WEBHOOK_SECRET", "")
561
+
562
+ if secret:
563
+ expected = hmac.new(
564
+ secret.encode('utf-8'),
565
+ body,
566
+ hashlib.sha256
567
+ ).hexdigest()
568
+
569
+ if not hmac.compare_digest(expected, signature):
570
+ raise HTTPException(status_code=401, detail="Invalid signature")
571
+
572
+ # 解析数据
493
573
  data = await request.json()
494
574
  event = data.get("event")
495
575
  user_data = data.get("data", {})
496
576
 
497
- # 验证签名
498
- signature = request.headers.get("X-Webhook-Signature")
499
- # ... 验证逻辑
500
-
501
577
  if event == "user.created":
502
578
  adapter = MyLegacyAdapter(db, sync_config)
503
579
  if not adapter.get_user_by_unique_field(user_data["username"]):
@@ -515,6 +591,14 @@ async def receive_auth_webhook(request: Request, db: Session = Depends(get_db)):
515
591
  return {"success": True}
516
592
  ```
517
593
 
594
+ **Webhook 签名验证说明**
595
+
596
+ SDK 的 `register_webhook_router` 会自动处理签名验证:
597
+ - 从请求头 `X-Webhook-Signature` 获取签名
598
+ - 从环境变量读取密钥(默认 `AIGC_AUTH_WEBHOOK_SECRET`)
599
+ - 使用 HMAC-SHA256 算法验证签名
600
+ - 签名不匹配时返回 401 错误
601
+
518
602
  #### 6. 执行初始化同步
519
603
 
520
604
  ```python
@@ -635,10 +719,41 @@ from huace_aigc_auth_client import (
635
719
  SyncResult,
636
720
  create_sync_config,
637
721
  create_default_field_mappings,
722
+
723
+ # Webhook 接收
724
+ register_webhook_router,
725
+ verify_webhook_signature,
638
726
  )
639
727
  ```
640
728
 
641
- ---
729
+ ---5 (2026-01-15)
730
+
731
+ #### 新增功能
732
+
733
+ 1. **Webhook 接收功能**
734
+ - 新增 `register_webhook_router()` 函数,快速注册 webhook 接收路由
735
+ - 自动处理签名验证、请求解析和错误处理
736
+ - 支持自定义前缀、密钥环境变量和标签
737
+ - 新增 `verify_webhook_signature()` 工具函数
738
+
739
+ #### 使用示例
740
+
741
+ ```python
742
+ from fastapi import APIRouter
743
+ from huace_aigc_auth_client import register_webhook_router
744
+
745
+ api_router = APIRouter()
746
+
747
+ async def my_handler(data: dict) -> dict:
748
+ event = data.get("event")
749
+ # 处理逻辑...
750
+ return {"status": "ok"}
751
+
752
+ # 注册 webhook 路由
753
+ register_webhook_router(api_router, my_handler)
754
+ ```
755
+
756
+ ### v1.1.
642
757
 
643
758
  ## API 变更日志
644
759
 
@@ -20,7 +20,7 @@ pip install huace-aigc-auth-client
20
20
  AIGC_AUTH_APP_ID=your_app_id
21
21
  AIGC_AUTH_APP_SECRET=your_app_secret
22
22
 
23
- # 可选:鉴权服务地址(默认为生产环境)
23
+ # 可选:鉴权服务地址(默认为生产环境)- 测试环境鉴权地址:https://auth-test.aigc.huacemedia.com/aigc-auth/api/v1
24
24
  AIGC_AUTH_BASE_URL=https://aigc-auth.huacemedia.com/aigc-auth/api/v1
25
25
  ```
26
26
 
@@ -303,21 +303,21 @@ except AigcAuthError as e:
303
303
 
304
304
  ```
305
305
  ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
306
- │ aigc-auth │────▶│ SDK 同步层 │────▶│ 旧系统
307
- │ (鉴权中心) │ │ (字段映射) │ │ (用户表)
306
+ │ aigc-auth │────▶│ SDK 同步层 │────▶│ 旧系统
307
+ │ (鉴权中心) │ │ (字段映射) │ │ (用户表)
308
308
  └─────────────────┘ └─────────────────┘ └─────────────────┘
309
309
  │ │ │
310
- │ 1. 初始化同步 │ │
310
+ │ 1. 初始化同步 │ │
311
311
  │◀──────────────────────────────────────────────│
312
- │ (批量同步旧用户到 auth)
312
+ │ (批量同步旧用户到 auth)
313
313
  │ │ │
314
- │ 2. 增量同步 │ │
314
+ │ 2. 增量同步 │ │
315
315
  │──────────────────────▶│──────────────────────▶│
316
- │ (auth 新用户自动同步到旧系统)
316
+ │ (auth 新用户自动同步到旧系统)
317
317
  │ │ │
318
- │ 3. Webhook 推送 │ │
318
+ │ 3. Webhook 推送 │ │
319
319
  │──────────────────────────────────────────────▶│
320
- │ (用户变更主动通知)
320
+ │ (用户变更主动通知)
321
321
  ```
322
322
 
323
323
  ### 快速开始
@@ -332,7 +332,7 @@ AIGC_AUTH_BASE_URL=https://aigc-auth.huacemedia.com/aigc-auth/api/v1
332
332
 
333
333
  # 同步配置
334
334
  AIGC_AUTH_SYNC_ENABLED=true
335
- AIGC_AUTH_SYNC_PASSWORD=Abc@123456
335
+ AIGC_AUTH_SYNC_PASSWORD=通用密码
336
336
  AIGC_AUTH_WEBHOOK_URL=https://your-domain.com/api/v1/webhook/auth
337
337
  AIGC_AUTH_WEBHOOK_SECRET=your_secret
338
338
  ```
@@ -382,7 +382,7 @@ field_mappings = [
382
382
  sync_config = create_sync_config(
383
383
  field_mappings=field_mappings,
384
384
  password_mode=PasswordMode.UNIFIED,
385
- unified_password="Abc@123456",
385
+ unified_password="通用密码",
386
386
  webhook_url="https://your-domain.com/api/v1/webhook/auth",
387
387
  )
388
388
  ```
@@ -461,18 +461,94 @@ async def auth_middleware(request, call_next):
461
461
 
462
462
  #### 5. 添加 Webhook 接收端点
463
463
 
464
+ **推荐方式:使用 SDK 提供的通用 Webhook 路由**
465
+
464
466
  ```python
467
+ from fastapi import APIRouter
468
+ from huace_aigc_auth_client import register_webhook_router
469
+
470
+ api_router = APIRouter()
471
+
472
+ # 定义 webhook 处理函数
473
+ async def handle_webhook(data: dict) -> dict:
474
+ """
475
+ 处理来自 aigc-auth 的 webhook 通知
476
+
477
+ Args:
478
+ data: webhook 数据,包含 event 和 data 字段
479
+
480
+ Returns:
481
+ dict: 处理结果
482
+ """
483
+ from your_app.db import get_db_session
484
+
485
+ event = data.get("event")
486
+ user_data = data.get("data", {})
487
+
488
+ # 创建数据库会话
489
+ async with get_db_session() as db:
490
+ adapter = MyLegacyAdapter(db, sync_config)
491
+
492
+ if event == "user.created":
493
+ # 处理用户创建事件
494
+ if not adapter.get_user_by_unique_field(user_data["username"]):
495
+ legacy_data = adapter.transform_auth_to_legacy(user_data)
496
+ legacy_data["password"] = sync_config.unified_password
497
+ adapter.create_user(legacy_data)
498
+ await db.commit()
499
+
500
+ elif event == "user.updated":
501
+ # 处理用户更新事件
502
+ legacy_data = adapter.transform_auth_to_legacy(user_data)
503
+ adapter.update_user(user_data["username"], legacy_data)
504
+ await db.commit()
505
+
506
+ return {"status": "ok", "event": event}
507
+
508
+ # 注册 webhook 路由(自动处理签名验证)
509
+ register_webhook_router(
510
+ api_router,
511
+ handler=handle_webhook,
512
+ prefix="/webhook", # 可选,默认 "/webhook"
513
+ secret_env_key="aigc-auth-webhook-secret", # 可选,在 auth 后台配置
514
+ tags=["Webhook"] # 可选,默认 ["Webhook"]
515
+ )
516
+
517
+ # webhook 端点将自动创建在: /webhook/auth
518
+ ```
519
+
520
+ **传统方式:手动实现 Webhook 端点**
521
+
522
+ ```python
523
+ import hmac
524
+ import hashlib
525
+ import os
526
+
465
527
  @app.post("/api/v1/webhook/auth")
466
528
  async def receive_auth_webhook(request: Request, db: Session = Depends(get_db)):
467
529
  """接收 aigc-auth 的用户变更通知"""
530
+ # 获取原始请求体
531
+ body = await request.body()
532
+
533
+ # 验证签名
534
+ signature = request.headers.get("X-Webhook-Signature", "")
535
+ secret = os.getenv("AIGC_AUTH_WEBHOOK_SECRET", "")
536
+
537
+ if secret:
538
+ expected = hmac.new(
539
+ secret.encode('utf-8'),
540
+ body,
541
+ hashlib.sha256
542
+ ).hexdigest()
543
+
544
+ if not hmac.compare_digest(expected, signature):
545
+ raise HTTPException(status_code=401, detail="Invalid signature")
546
+
547
+ # 解析数据
468
548
  data = await request.json()
469
549
  event = data.get("event")
470
550
  user_data = data.get("data", {})
471
551
 
472
- # 验证签名
473
- signature = request.headers.get("X-Webhook-Signature")
474
- # ... 验证逻辑
475
-
476
552
  if event == "user.created":
477
553
  adapter = MyLegacyAdapter(db, sync_config)
478
554
  if not adapter.get_user_by_unique_field(user_data["username"]):
@@ -490,6 +566,14 @@ async def receive_auth_webhook(request: Request, db: Session = Depends(get_db)):
490
566
  return {"success": True}
491
567
  ```
492
568
 
569
+ **Webhook 签名验证说明**
570
+
571
+ SDK 的 `register_webhook_router` 会自动处理签名验证:
572
+ - 从请求头 `X-Webhook-Signature` 获取签名
573
+ - 从环境变量读取密钥(默认 `AIGC_AUTH_WEBHOOK_SECRET`)
574
+ - 使用 HMAC-SHA256 算法验证签名
575
+ - 签名不匹配时返回 401 错误
576
+
493
577
  #### 6. 执行初始化同步
494
578
 
495
579
  ```python
@@ -610,10 +694,41 @@ from huace_aigc_auth_client import (
610
694
  SyncResult,
611
695
  create_sync_config,
612
696
  create_default_field_mappings,
697
+
698
+ # Webhook 接收
699
+ register_webhook_router,
700
+ verify_webhook_signature,
613
701
  )
614
702
  ```
615
703
 
616
- ---
704
+ ---5 (2026-01-15)
705
+
706
+ #### 新增功能
707
+
708
+ 1. **Webhook 接收功能**
709
+ - 新增 `register_webhook_router()` 函数,快速注册 webhook 接收路由
710
+ - 自动处理签名验证、请求解析和错误处理
711
+ - 支持自定义前缀、密钥环境变量和标签
712
+ - 新增 `verify_webhook_signature()` 工具函数
713
+
714
+ #### 使用示例
715
+
716
+ ```python
717
+ from fastapi import APIRouter
718
+ from huace_aigc_auth_client import register_webhook_router
719
+
720
+ api_router = APIRouter()
721
+
722
+ async def my_handler(data: dict) -> dict:
723
+ event = data.get("event")
724
+ # 处理逻辑...
725
+ return {"status": "ok"}
726
+
727
+ # 注册 webhook 路由
728
+ register_webhook_router(api_router, my_handler)
729
+ ```
730
+
731
+ ### v1.1.
617
732
 
618
733
  ## API 变更日志
619
734
 
@@ -98,4 +98,4 @@ __all__ = [
98
98
  "register_webhook_router",
99
99
  "verify_webhook_signature",
100
100
  ]
101
- __version__ = "1.1.5"
101
+ __version__ = "1.1.7"
@@ -195,14 +195,14 @@ class LegacySystemAdapter(ABC):
195
195
  """
196
196
  raise NotImplementedError("Subclass must implement get_all_users_async method")
197
197
 
198
- async def upsert_user_async(self, user_data: Dict[str, Any]) -> Dict[str, Any]:
198
+ async def upsert_user_async(self, user_data: Dict[str, Any], auth_data: Dict[str, Any] = None) -> Dict[str, Any]:
199
199
  """异步创建或更新用户(存在则更新,不存在则新增)
200
200
 
201
201
  这是一个默认实现,子类可以选择性覆盖以优化性能。
202
202
 
203
203
  Args:
204
204
  user_data: 用户数据字典(必须包含 username)
205
-
205
+ auth_data: 鉴权系统用户数据字典(可选)
206
206
  Returns:
207
207
  Dict: 操作结果 {"created": bool, "user_id": Any}
208
208
  """
@@ -215,6 +215,9 @@ class LegacySystemAdapter(ABC):
215
215
 
216
216
  if existing:
217
217
  # 用户存在,执行更新
218
+ if not auth_data or auth_data.get("updatedFields") is None or len(auth_data.get("updatedFields")) == 0:
219
+ # 如果没有提供 auth_data 或 updatedFields,则不更新
220
+ return {"created": False, "user_id": existing.get("id")}
218
221
  await self._update_user_async(username, user_data)
219
222
  return {"created": False, "user_id": existing.get("id")}
220
223
  else:
@@ -92,7 +92,7 @@ class AigcAuthClient:
92
92
  client = AigcAuthClient(
93
93
  app_id="your_app_id",
94
94
  app_secret="your_app_secret",
95
- base_url="https://aigc-auth.huacemedia.com/aigc-auth/api/v1" # 可选
95
+ base_url="https://aigc-auth.huacemedia.com/aigc-auth/api/v1"
96
96
  )
97
97
 
98
98
  # 验证 token
@@ -271,6 +271,7 @@ class AigcAuthClient:
271
271
  result = response.json()
272
272
 
273
273
  if result.get("code") != 0:
274
+ logger.error(f"AigcAuthClient 请求错误: {result}")
274
275
  raise AigcAuthError(
275
276
  result.get("code", -1),
276
277
  result.get("message", "未知错误")
@@ -285,6 +286,7 @@ class AigcAuthClient:
285
286
  return response_data
286
287
 
287
288
  except requests.exceptions.RequestException as e:
289
+ logger.error(f"AigcAuthClient 请求失败: {str(e)}")
288
290
  raise AigcAuthError(-1, f"请求失败: {str(e)}")
289
291
 
290
292
  def verify_token(self, token: str) -> TokenVerifyResult:
@@ -599,6 +601,7 @@ class AuthMiddleware:
599
601
  token = self._extract_token(authorization)
600
602
 
601
603
  if not token:
604
+ logger.warning("AuthMiddleware未提供认证信息")
602
605
  return JSONResponse(
603
606
  status_code=401,
604
607
  content={"code": 401, "message": "未提供认证信息", "data": None}
@@ -616,6 +619,7 @@ class AuthMiddleware:
616
619
  if user_info_callback:
617
620
  await user_info_callback(request, user_info)
618
621
  except AigcAuthError as e:
622
+ logger.error(f"AuthMiddleware认证失败: {e.message}")
619
623
  return JSONResponse(
620
624
  status_code=401,
621
625
  content={"code": e.code, "message": e.message, "data": None}
@@ -644,6 +648,7 @@ class AuthMiddleware:
644
648
  token = self._extract_token(authorization)
645
649
 
646
650
  if not token:
651
+ logger.warning("AuthMiddleware未提供认证信息")
647
652
  return jsonify({
648
653
  "code": 401,
649
654
  "message": "未提供认证信息",
@@ -658,6 +663,7 @@ class AuthMiddleware:
658
663
  if user_info_callback:
659
664
  user_info_callback(request, user_info)
660
665
  except AigcAuthError as e:
666
+ logger.error(f"AuthMiddleware认证失败: {e.message}")
661
667
  return jsonify({
662
668
  "code": e.code,
663
669
  "message": e.message,
@@ -712,6 +718,7 @@ def create_fastapi_auth_dependency(client: AigcAuthClient):
712
718
  user_info = client.get_user_info_from_header(authorization)
713
719
 
714
720
  if user_info is None:
721
+ logger.warning("FastAPI依赖未登录或Token已过期")
715
722
  raise HTTPException(status_code=401, detail="未登录或 Token 已过期")
716
723
 
717
724
  return user_info
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: huace-aigc-auth-client
3
- Version: 1.1.5
3
+ Version: 1.1.7
4
4
  Summary: 华策AIGC Auth Client - 提供 Token 验证、用户信息获取、权限检查、旧系统接入等功能
5
5
  Author-email: Huace <support@huace.com>
6
6
  License: MIT
@@ -45,7 +45,7 @@ pip install huace-aigc-auth-client
45
45
  AIGC_AUTH_APP_ID=your_app_id
46
46
  AIGC_AUTH_APP_SECRET=your_app_secret
47
47
 
48
- # 可选:鉴权服务地址(默认为生产环境)
48
+ # 可选:鉴权服务地址(默认为生产环境)- 测试环境鉴权地址:https://auth-test.aigc.huacemedia.com/aigc-auth/api/v1
49
49
  AIGC_AUTH_BASE_URL=https://aigc-auth.huacemedia.com/aigc-auth/api/v1
50
50
  ```
51
51
 
@@ -328,21 +328,21 @@ except AigcAuthError as e:
328
328
 
329
329
  ```
330
330
  ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
331
- │ aigc-auth │────▶│ SDK 同步层 │────▶│ 旧系统
332
- │ (鉴权中心) │ │ (字段映射) │ │ (用户表)
331
+ │ aigc-auth │────▶│ SDK 同步层 │────▶│ 旧系统
332
+ │ (鉴权中心) │ │ (字段映射) │ │ (用户表)
333
333
  └─────────────────┘ └─────────────────┘ └─────────────────┘
334
334
  │ │ │
335
- │ 1. 初始化同步 │ │
335
+ │ 1. 初始化同步 │ │
336
336
  │◀──────────────────────────────────────────────│
337
- │ (批量同步旧用户到 auth)
337
+ │ (批量同步旧用户到 auth)
338
338
  │ │ │
339
- │ 2. 增量同步 │ │
339
+ │ 2. 增量同步 │ │
340
340
  │──────────────────────▶│──────────────────────▶│
341
- │ (auth 新用户自动同步到旧系统)
341
+ │ (auth 新用户自动同步到旧系统)
342
342
  │ │ │
343
- │ 3. Webhook 推送 │ │
343
+ │ 3. Webhook 推送 │ │
344
344
  │──────────────────────────────────────────────▶│
345
- │ (用户变更主动通知)
345
+ │ (用户变更主动通知)
346
346
  ```
347
347
 
348
348
  ### 快速开始
@@ -357,7 +357,7 @@ AIGC_AUTH_BASE_URL=https://aigc-auth.huacemedia.com/aigc-auth/api/v1
357
357
 
358
358
  # 同步配置
359
359
  AIGC_AUTH_SYNC_ENABLED=true
360
- AIGC_AUTH_SYNC_PASSWORD=Abc@123456
360
+ AIGC_AUTH_SYNC_PASSWORD=通用密码
361
361
  AIGC_AUTH_WEBHOOK_URL=https://your-domain.com/api/v1/webhook/auth
362
362
  AIGC_AUTH_WEBHOOK_SECRET=your_secret
363
363
  ```
@@ -407,7 +407,7 @@ field_mappings = [
407
407
  sync_config = create_sync_config(
408
408
  field_mappings=field_mappings,
409
409
  password_mode=PasswordMode.UNIFIED,
410
- unified_password="Abc@123456",
410
+ unified_password="通用密码",
411
411
  webhook_url="https://your-domain.com/api/v1/webhook/auth",
412
412
  )
413
413
  ```
@@ -486,18 +486,94 @@ async def auth_middleware(request, call_next):
486
486
 
487
487
  #### 5. 添加 Webhook 接收端点
488
488
 
489
+ **推荐方式:使用 SDK 提供的通用 Webhook 路由**
490
+
489
491
  ```python
492
+ from fastapi import APIRouter
493
+ from huace_aigc_auth_client import register_webhook_router
494
+
495
+ api_router = APIRouter()
496
+
497
+ # 定义 webhook 处理函数
498
+ async def handle_webhook(data: dict) -> dict:
499
+ """
500
+ 处理来自 aigc-auth 的 webhook 通知
501
+
502
+ Args:
503
+ data: webhook 数据,包含 event 和 data 字段
504
+
505
+ Returns:
506
+ dict: 处理结果
507
+ """
508
+ from your_app.db import get_db_session
509
+
510
+ event = data.get("event")
511
+ user_data = data.get("data", {})
512
+
513
+ # 创建数据库会话
514
+ async with get_db_session() as db:
515
+ adapter = MyLegacyAdapter(db, sync_config)
516
+
517
+ if event == "user.created":
518
+ # 处理用户创建事件
519
+ if not adapter.get_user_by_unique_field(user_data["username"]):
520
+ legacy_data = adapter.transform_auth_to_legacy(user_data)
521
+ legacy_data["password"] = sync_config.unified_password
522
+ adapter.create_user(legacy_data)
523
+ await db.commit()
524
+
525
+ elif event == "user.updated":
526
+ # 处理用户更新事件
527
+ legacy_data = adapter.transform_auth_to_legacy(user_data)
528
+ adapter.update_user(user_data["username"], legacy_data)
529
+ await db.commit()
530
+
531
+ return {"status": "ok", "event": event}
532
+
533
+ # 注册 webhook 路由(自动处理签名验证)
534
+ register_webhook_router(
535
+ api_router,
536
+ handler=handle_webhook,
537
+ prefix="/webhook", # 可选,默认 "/webhook"
538
+ secret_env_key="aigc-auth-webhook-secret", # 可选,在 auth 后台配置
539
+ tags=["Webhook"] # 可选,默认 ["Webhook"]
540
+ )
541
+
542
+ # webhook 端点将自动创建在: /webhook/auth
543
+ ```
544
+
545
+ **传统方式:手动实现 Webhook 端点**
546
+
547
+ ```python
548
+ import hmac
549
+ import hashlib
550
+ import os
551
+
490
552
  @app.post("/api/v1/webhook/auth")
491
553
  async def receive_auth_webhook(request: Request, db: Session = Depends(get_db)):
492
554
  """接收 aigc-auth 的用户变更通知"""
555
+ # 获取原始请求体
556
+ body = await request.body()
557
+
558
+ # 验证签名
559
+ signature = request.headers.get("X-Webhook-Signature", "")
560
+ secret = os.getenv("AIGC_AUTH_WEBHOOK_SECRET", "")
561
+
562
+ if secret:
563
+ expected = hmac.new(
564
+ secret.encode('utf-8'),
565
+ body,
566
+ hashlib.sha256
567
+ ).hexdigest()
568
+
569
+ if not hmac.compare_digest(expected, signature):
570
+ raise HTTPException(status_code=401, detail="Invalid signature")
571
+
572
+ # 解析数据
493
573
  data = await request.json()
494
574
  event = data.get("event")
495
575
  user_data = data.get("data", {})
496
576
 
497
- # 验证签名
498
- signature = request.headers.get("X-Webhook-Signature")
499
- # ... 验证逻辑
500
-
501
577
  if event == "user.created":
502
578
  adapter = MyLegacyAdapter(db, sync_config)
503
579
  if not adapter.get_user_by_unique_field(user_data["username"]):
@@ -515,6 +591,14 @@ async def receive_auth_webhook(request: Request, db: Session = Depends(get_db)):
515
591
  return {"success": True}
516
592
  ```
517
593
 
594
+ **Webhook 签名验证说明**
595
+
596
+ SDK 的 `register_webhook_router` 会自动处理签名验证:
597
+ - 从请求头 `X-Webhook-Signature` 获取签名
598
+ - 从环境变量读取密钥(默认 `AIGC_AUTH_WEBHOOK_SECRET`)
599
+ - 使用 HMAC-SHA256 算法验证签名
600
+ - 签名不匹配时返回 401 错误
601
+
518
602
  #### 6. 执行初始化同步
519
603
 
520
604
  ```python
@@ -635,10 +719,41 @@ from huace_aigc_auth_client import (
635
719
  SyncResult,
636
720
  create_sync_config,
637
721
  create_default_field_mappings,
722
+
723
+ # Webhook 接收
724
+ register_webhook_router,
725
+ verify_webhook_signature,
638
726
  )
639
727
  ```
640
728
 
641
- ---
729
+ ---5 (2026-01-15)
730
+
731
+ #### 新增功能
732
+
733
+ 1. **Webhook 接收功能**
734
+ - 新增 `register_webhook_router()` 函数,快速注册 webhook 接收路由
735
+ - 自动处理签名验证、请求解析和错误处理
736
+ - 支持自定义前缀、密钥环境变量和标签
737
+ - 新增 `verify_webhook_signature()` 工具函数
738
+
739
+ #### 使用示例
740
+
741
+ ```python
742
+ from fastapi import APIRouter
743
+ from huace_aigc_auth_client import register_webhook_router
744
+
745
+ api_router = APIRouter()
746
+
747
+ async def my_handler(data: dict) -> dict:
748
+ event = data.get("event")
749
+ # 处理逻辑...
750
+ return {"status": "ok"}
751
+
752
+ # 注册 webhook 路由
753
+ register_webhook_router(api_router, my_handler)
754
+ ```
755
+
756
+ ### v1.1.
642
757
 
643
758
  ## API 变更日志
644
759
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "huace-aigc-auth-client"
7
- version = "1.1.5"
7
+ version = "1.1.7"
8
8
  description = "华策AIGC Auth Client - 提供 Token 验证、用户信息获取、权限检查、旧系统接入等功能"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.7"