huace-aigc-auth-client 1.1.33__py3-none-any.whl → 1.1.34__py3-none-any.whl
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.
- huace_aigc_auth_client/__init__.py +1 -1
- {huace_aigc_auth_client-1.1.33.dist-info → huace_aigc_auth_client-1.1.34.dist-info}/METADATA +354 -1
- {huace_aigc_auth_client-1.1.33.dist-info → huace_aigc_auth_client-1.1.34.dist-info}/RECORD +6 -6
- {huace_aigc_auth_client-1.1.33.dist-info → huace_aigc_auth_client-1.1.34.dist-info}/WHEEL +0 -0
- {huace_aigc_auth_client-1.1.33.dist-info → huace_aigc_auth_client-1.1.34.dist-info}/licenses/LICENSE +0 -0
- {huace_aigc_auth_client-1.1.33.dist-info → huace_aigc_auth_client-1.1.34.dist-info}/top_level.txt +0 -0
{huace_aigc_auth_client-1.1.33.dist-info → huace_aigc_auth_client-1.1.34.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: huace-aigc-auth-client
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.34
|
|
4
4
|
Summary: 华策AIGC Auth Client - 提供 Token 验证、用户信息获取、权限检查、旧系统接入等功能
|
|
5
5
|
Author-email: Huace <support@huace.com>
|
|
6
6
|
License: MIT
|
|
@@ -691,6 +691,329 @@ sync_config = create_sync_config(
|
|
|
691
691
|
|
|
692
692
|
---
|
|
693
693
|
|
|
694
|
+
## 高级功能
|
|
695
|
+
|
|
696
|
+
### API 统计收集
|
|
697
|
+
|
|
698
|
+
SDK 提供了接口统计收集功能,自动收集和上报 API 调用数据到鉴权中心。
|
|
699
|
+
|
|
700
|
+
#### 1. 初始化统计收集器
|
|
701
|
+
|
|
702
|
+
```python
|
|
703
|
+
from huace_aigc_auth_client import init_api_stats_collector
|
|
704
|
+
|
|
705
|
+
# 仅仅示例,SDK 接入鉴权会默认启用数据收集功能(可以手动传参关闭)
|
|
706
|
+
# 在应用启动时初始化
|
|
707
|
+
init_api_stats_collector(
|
|
708
|
+
api_url='http://auth.example.com/api/sdk',
|
|
709
|
+
app_id='your-app-id',
|
|
710
|
+
app_secret='your-app-secret',
|
|
711
|
+
batch_size=10, # 批量提交大小
|
|
712
|
+
flush_interval=5.0, # 刷新间隔(秒)
|
|
713
|
+
enabled=True # 是否启用
|
|
714
|
+
)
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
#### 2. 在中间件中自动收集
|
|
718
|
+
|
|
719
|
+
**FastAPI 示例:**
|
|
720
|
+
|
|
721
|
+
```python
|
|
722
|
+
from fastapi import FastAPI, Request
|
|
723
|
+
from huace_aigc_auth_client import collect_api_stat
|
|
724
|
+
import time
|
|
725
|
+
|
|
726
|
+
app = FastAPI()
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
# 仅仅示例,SDK 内默认会启用数据收集未 exclude 的接口(可以手动传参关闭)
|
|
730
|
+
@app.middleware("http")
|
|
731
|
+
async def monitor_middleware(request: Request, call_next):
|
|
732
|
+
start_time = time.time()
|
|
733
|
+
|
|
734
|
+
try:
|
|
735
|
+
response = await call_next(request)
|
|
736
|
+
response_time = time.time() - start_time
|
|
737
|
+
|
|
738
|
+
# 从请求上下文获取 token
|
|
739
|
+
token = request.state.user_info.token if hasattr(request.state, 'user_info') else None
|
|
740
|
+
|
|
741
|
+
# 收集统计(会自动过滤 3xx 重定向请求)
|
|
742
|
+
collect_api_stat(
|
|
743
|
+
api_path=request.url.path,
|
|
744
|
+
api_method=request.method,
|
|
745
|
+
status_code=response.status_code,
|
|
746
|
+
response_time=response_time,
|
|
747
|
+
token=token,
|
|
748
|
+
request_params={
|
|
749
|
+
'headers': dict(request.headers),
|
|
750
|
+
'query_params': dict(request.query_params)
|
|
751
|
+
}
|
|
752
|
+
)
|
|
753
|
+
|
|
754
|
+
return response
|
|
755
|
+
except Exception as e:
|
|
756
|
+
response_time = time.time() - start_time
|
|
757
|
+
collect_api_stat(
|
|
758
|
+
api_path=request.url.path,
|
|
759
|
+
api_method=request.method,
|
|
760
|
+
status_code=500,
|
|
761
|
+
response_time=response_time,
|
|
762
|
+
token=token,
|
|
763
|
+
error_message=str(e)
|
|
764
|
+
)
|
|
765
|
+
raise
|
|
766
|
+
|
|
767
|
+
@app.on_event("shutdown")
|
|
768
|
+
async def shutdown_event():
|
|
769
|
+
from huace_aigc_auth_client import stop_api_stats_collector
|
|
770
|
+
stop_api_stats_collector()
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
**特性说明:**
|
|
774
|
+
- 异步队列收集,不阻塞主流程
|
|
775
|
+
- 批量提交,减少网络开销
|
|
776
|
+
- 自动过滤 3xx 重定向请求
|
|
777
|
+
- 按 token 分组提交
|
|
778
|
+
- 静默失败,不影响主业务
|
|
779
|
+
|
|
780
|
+
---
|
|
781
|
+
|
|
782
|
+
### 认证请求封装
|
|
783
|
+
|
|
784
|
+
SDK 提供了 `auth_request` 函数,封装标准的 HTTP 请求,自动添加认证信息并上报统计。
|
|
785
|
+
|
|
786
|
+
#### 1. 基本使用
|
|
787
|
+
|
|
788
|
+
```python
|
|
789
|
+
from huace_aigc_auth_client import auth_request, set_request_context
|
|
790
|
+
|
|
791
|
+
# 设置请求上下文(通常在中间件中完成)
|
|
792
|
+
set_request_context(
|
|
793
|
+
app_id='your-app-id',
|
|
794
|
+
app_secret='your-app-secret',
|
|
795
|
+
token='user-access-token',
|
|
796
|
+
ip_address='192.168.1.1',
|
|
797
|
+
user_agent='Mozilla/5.0...',
|
|
798
|
+
trace_id='trace-123'
|
|
799
|
+
)
|
|
800
|
+
|
|
801
|
+
# 发起请求(会自动添加认证信息)
|
|
802
|
+
response = auth_request('GET', 'https://api.example.com/data')
|
|
803
|
+
print(response.json())
|
|
804
|
+
```
|
|
805
|
+
|
|
806
|
+
#### 2. 带参数的请求
|
|
807
|
+
|
|
808
|
+
```python
|
|
809
|
+
# GET 请求带查询参数
|
|
810
|
+
response = auth_request(
|
|
811
|
+
'GET',
|
|
812
|
+
'https://api.example.com/users',
|
|
813
|
+
params={'page': 1, 'size': 10}
|
|
814
|
+
)
|
|
815
|
+
|
|
816
|
+
# POST 请求带 JSON 数据
|
|
817
|
+
response = auth_request(
|
|
818
|
+
'POST',
|
|
819
|
+
'https://api.example.com/users',
|
|
820
|
+
json={'name': 'John', 'email': 'john@example.com'}
|
|
821
|
+
)
|
|
822
|
+
|
|
823
|
+
# POST 请求带表单数据
|
|
824
|
+
response = auth_request(
|
|
825
|
+
'POST',
|
|
826
|
+
'https://api.example.com/upload',
|
|
827
|
+
data={'field1': 'value1', 'field2': 'value2'}
|
|
828
|
+
)
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
#### 3. 异步请求(httpx)
|
|
832
|
+
|
|
833
|
+
需要安装 httpx:`pip install httpx`
|
|
834
|
+
|
|
835
|
+
```python
|
|
836
|
+
from huace_aigc_auth_client import async_auth_httpx_request, AsyncAuthClient
|
|
837
|
+
import asyncio
|
|
838
|
+
|
|
839
|
+
# 方式1:使用函数
|
|
840
|
+
async def example1():
|
|
841
|
+
response = await async_auth_httpx_request('GET', 'https://api.example.com/data')
|
|
842
|
+
print(response.json())
|
|
843
|
+
|
|
844
|
+
# 方式2:使用 AsyncAuthClient(推荐用于多个请求)
|
|
845
|
+
async def example2():
|
|
846
|
+
async with AsyncAuthClient(timeout=10.0) as client:
|
|
847
|
+
# POST 请求
|
|
848
|
+
response = await client.post(
|
|
849
|
+
'https://api.example.com/users',
|
|
850
|
+
json={'name': 'John'}
|
|
851
|
+
)
|
|
852
|
+
|
|
853
|
+
# GET 请求
|
|
854
|
+
response = await client.get(
|
|
855
|
+
'https://api.example.com/users',
|
|
856
|
+
params={'page': 1}
|
|
857
|
+
)
|
|
858
|
+
|
|
859
|
+
asyncio.run(example1())
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
**自动添加的请求头:**
|
|
863
|
+
- `X-App-ID`: 应用ID
|
|
864
|
+
- `X-App-Secret`: 应用密钥
|
|
865
|
+
- `Authorization`: Bearer token
|
|
866
|
+
- `x-real-ip`: 客户端真实IP
|
|
867
|
+
- `user-agent`: User Agent
|
|
868
|
+
- `X-Trace-ID`: 追踪ID
|
|
869
|
+
|
|
870
|
+
---
|
|
871
|
+
|
|
872
|
+
### 用户上下文管理
|
|
873
|
+
|
|
874
|
+
SDK 提供了完整的用户上下文管理功能,支持同步和异步环境。
|
|
875
|
+
|
|
876
|
+
#### 1. 设置和获取用户信息
|
|
877
|
+
|
|
878
|
+
```python
|
|
879
|
+
from huace_aigc_auth_client import (
|
|
880
|
+
set_current_user,
|
|
881
|
+
get_current_user,
|
|
882
|
+
get_current_user_id,
|
|
883
|
+
get_current_username,
|
|
884
|
+
is_current_user_admin
|
|
885
|
+
)
|
|
886
|
+
|
|
887
|
+
# 在中间件中设置
|
|
888
|
+
set_current_user({
|
|
889
|
+
'user_id': 123,
|
|
890
|
+
'username': 'john',
|
|
891
|
+
'app_id': 1,
|
|
892
|
+
'app_code': 'myapp',
|
|
893
|
+
'token': 'xxx',
|
|
894
|
+
'roles': ['admin'],
|
|
895
|
+
'permissions': ['user:read', 'user:write'],
|
|
896
|
+
'is_admin': True
|
|
897
|
+
})
|
|
898
|
+
|
|
899
|
+
# 在业务代码中获取
|
|
900
|
+
def some_business_logic():
|
|
901
|
+
user = get_current_user()
|
|
902
|
+
user_id = get_current_user_id()
|
|
903
|
+
username = get_current_username()
|
|
904
|
+
|
|
905
|
+
if user:
|
|
906
|
+
print(f"当前用户: {username} ({user_id})")
|
|
907
|
+
|
|
908
|
+
if is_current_user_admin():
|
|
909
|
+
print("当前用户是管理员")
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
#### 2. 请求上下文管理
|
|
913
|
+
|
|
914
|
+
```python
|
|
915
|
+
from huace_aigc_auth_client import (
|
|
916
|
+
set_request_context,
|
|
917
|
+
get_request_context,
|
|
918
|
+
get_client_ip,
|
|
919
|
+
get_user_agent,
|
|
920
|
+
get_trace_id
|
|
921
|
+
)
|
|
922
|
+
|
|
923
|
+
# 设置请求上下文
|
|
924
|
+
set_request_context(
|
|
925
|
+
ip_address='192.168.1.1',
|
|
926
|
+
user_agent='Mozilla/5.0...',
|
|
927
|
+
trace_id='trace-123',
|
|
928
|
+
app_id='your-app-id',
|
|
929
|
+
app_secret='your-app-secret',
|
|
930
|
+
token='user-token'
|
|
931
|
+
)
|
|
932
|
+
|
|
933
|
+
# 获取请求上下文信息
|
|
934
|
+
ctx = get_request_context()
|
|
935
|
+
ip = get_client_ip()
|
|
936
|
+
ua = get_user_agent()
|
|
937
|
+
trace = get_trace_id()
|
|
938
|
+
```
|
|
939
|
+
|
|
940
|
+
#### 3. 在 FastAPI 中集成
|
|
941
|
+
|
|
942
|
+
```python
|
|
943
|
+
from fastapi import FastAPI, Request, Depends
|
|
944
|
+
from huace_aigc_auth_client import (
|
|
945
|
+
set_current_user,
|
|
946
|
+
set_request_context,
|
|
947
|
+
get_current_user,
|
|
948
|
+
clear_current_user,
|
|
949
|
+
clear_request_context
|
|
950
|
+
)
|
|
951
|
+
|
|
952
|
+
app = FastAPI()
|
|
953
|
+
|
|
954
|
+
@app.middleware("http")
|
|
955
|
+
async def user_context_middleware(request: Request, call_next):
|
|
956
|
+
# 从认证中获取用户信息
|
|
957
|
+
user_info = request.state.user_info if hasattr(request.state, 'user_info') else None
|
|
958
|
+
|
|
959
|
+
if user_info:
|
|
960
|
+
# 设置用户上下文
|
|
961
|
+
set_current_user({
|
|
962
|
+
'user_id': user_info.id,
|
|
963
|
+
'username': user_info.username,
|
|
964
|
+
'app_id': getattr(user_info, 'app_id', None),
|
|
965
|
+
'is_admin': user_info.is_admin
|
|
966
|
+
})
|
|
967
|
+
|
|
968
|
+
# 设置请求上下文
|
|
969
|
+
set_request_context(
|
|
970
|
+
ip_address=request.client.host,
|
|
971
|
+
user_agent=request.headers.get('user-agent'),
|
|
972
|
+
trace_id=request.headers.get('x-trace-id'),
|
|
973
|
+
token=request.headers.get('authorization', '').replace('Bearer ', '')
|
|
974
|
+
)
|
|
975
|
+
|
|
976
|
+
try:
|
|
977
|
+
response = await call_next(request)
|
|
978
|
+
return response
|
|
979
|
+
finally:
|
|
980
|
+
clear_current_user()
|
|
981
|
+
clear_request_context()
|
|
982
|
+
|
|
983
|
+
# 在任意地方使用
|
|
984
|
+
def my_service_function():
|
|
985
|
+
user = get_current_user()
|
|
986
|
+
if user:
|
|
987
|
+
print(f"执行操作的用户: {user['username']}")
|
|
988
|
+
```
|
|
989
|
+
|
|
990
|
+
#### 4. 装饰器中使用
|
|
991
|
+
|
|
992
|
+
```python
|
|
993
|
+
from functools import wraps
|
|
994
|
+
from huace_aigc_auth_client import is_current_user_admin
|
|
995
|
+
|
|
996
|
+
def require_admin(func):
|
|
997
|
+
@wraps(func)
|
|
998
|
+
async def wrapper(*args, **kwargs):
|
|
999
|
+
if not is_current_user_admin():
|
|
1000
|
+
raise HTTPException(status_code=403, detail="需要管理员权限")
|
|
1001
|
+
return await func(*args, **kwargs)
|
|
1002
|
+
return wrapper
|
|
1003
|
+
|
|
1004
|
+
@require_admin
|
|
1005
|
+
async def admin_endpoint():
|
|
1006
|
+
return {"message": "管理员操作"}
|
|
1007
|
+
```
|
|
1008
|
+
|
|
1009
|
+
**特性说明:**
|
|
1010
|
+
- 使用 `threading.local()` 和 `contextvars.ContextVar` 实现
|
|
1011
|
+
- 同时支持同步和异步环境
|
|
1012
|
+
- 线程安全和异步任务隔离
|
|
1013
|
+
- 无需层层传递参数
|
|
1014
|
+
|
|
1015
|
+
---
|
|
1016
|
+
|
|
694
1017
|
## 导出清单
|
|
695
1018
|
|
|
696
1019
|
```python
|
|
@@ -720,6 +1043,36 @@ from huace_aigc_auth_client import (
|
|
|
720
1043
|
# Webhook 接收
|
|
721
1044
|
register_webhook_router,
|
|
722
1045
|
verify_webhook_signature,
|
|
1046
|
+
|
|
1047
|
+
# API 统计收集
|
|
1048
|
+
ApiStatsCollector,
|
|
1049
|
+
init_api_stats_collector,
|
|
1050
|
+
get_api_stats_collector,
|
|
1051
|
+
stop_api_stats_collector,
|
|
1052
|
+
collect_api_stat,
|
|
1053
|
+
|
|
1054
|
+
# 认证请求封装
|
|
1055
|
+
auth_request,
|
|
1056
|
+
async_auth_httpx_request,
|
|
1057
|
+
AsyncAuthClient,
|
|
1058
|
+
|
|
1059
|
+
# 用户上下文管理
|
|
1060
|
+
set_current_user,
|
|
1061
|
+
get_current_user,
|
|
1062
|
+
get_current_user_id,
|
|
1063
|
+
get_current_username,
|
|
1064
|
+
get_current_app_id,
|
|
1065
|
+
get_current_app_code,
|
|
1066
|
+
is_current_user_admin,
|
|
1067
|
+
clear_current_user,
|
|
1068
|
+
set_request_context,
|
|
1069
|
+
get_request_context,
|
|
1070
|
+
get_client_ip,
|
|
1071
|
+
get_user_agent,
|
|
1072
|
+
get_request_id,
|
|
1073
|
+
get_trace_id,
|
|
1074
|
+
get_request_token,
|
|
1075
|
+
clear_request_context,
|
|
723
1076
|
)
|
|
724
1077
|
```
|
|
725
1078
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
huace_aigc_auth_client/__init__.py,sha256=
|
|
1
|
+
huace_aigc_auth_client/__init__.py,sha256=ZrHUpyhR2qKqo9RJ39C2s7C3PeriyYvNvQMxtH7N6C8,6020
|
|
2
2
|
huace_aigc_auth_client/api_stats_collector.py,sha256=ADpjpHXMqn80YI4UltWHbzAO_szykU9ZCvwXgBRWFIM,11046
|
|
3
3
|
huace_aigc_auth_client/auth_request.py,sha256=wc23_Lz0ounJ0HSN0e49lfTKNEio80FbWXTKFaOrw8g,22684
|
|
4
4
|
huace_aigc_auth_client/legacy_adapter.py,sha256=TVCBAKejE2z2HQFsEwDW8LMiaIkXNfz3Mxv6_E-UJFY,24102
|
|
@@ -6,8 +6,8 @@ huace_aigc_auth_client/sdk.py,sha256=rproo913OAi37wz_rMYgxzP3F1YyY3nc5e35JS5WvoY
|
|
|
6
6
|
huace_aigc_auth_client/user_context.py,sha256=IqdX6Xd2jJwvij6Hc2qWAFWj5pn3wHqk0RBsaXKLP8g,6795
|
|
7
7
|
huace_aigc_auth_client/webhook.py,sha256=XQZYEbMoqIdqZWCGSTcedeDKJpDbUVSq5g08g-6Qucg,4124
|
|
8
8
|
huace_aigc_auth_client/webhook_flask.py,sha256=Iosu4dBtRhQZM_ytn-bn82MpVsyOiV28FBnt7Tfh31U,7225
|
|
9
|
-
huace_aigc_auth_client-1.1.
|
|
10
|
-
huace_aigc_auth_client-1.1.
|
|
11
|
-
huace_aigc_auth_client-1.1.
|
|
12
|
-
huace_aigc_auth_client-1.1.
|
|
13
|
-
huace_aigc_auth_client-1.1.
|
|
9
|
+
huace_aigc_auth_client-1.1.34.dist-info/licenses/LICENSE,sha256=z7dgC7KljhBLNvKjN15391nMj3aLt0gbud8-Yf1F8EQ,1063
|
|
10
|
+
huace_aigc_auth_client-1.1.34.dist-info/METADATA,sha256=8AlHIfXy0YxAZ9Z20Qcsq5sv7svOHjGY0rJp6cmJRvg,32415
|
|
11
|
+
huace_aigc_auth_client-1.1.34.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
12
|
+
huace_aigc_auth_client-1.1.34.dist-info/top_level.txt,sha256=kbv0nQ6PQ0JVneWPH7O2AbtlJnP7AjvFJ6JjM6ZEBxo,23
|
|
13
|
+
huace_aigc_auth_client-1.1.34.dist-info/RECORD,,
|
|
File without changes
|
{huace_aigc_auth_client-1.1.33.dist-info → huace_aigc_auth_client-1.1.34.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
{huace_aigc_auth_client-1.1.33.dist-info → huace_aigc_auth_client-1.1.34.dist-info}/top_level.txt
RENAMED
|
File without changes
|