lesscode-flask 0.2.63__tar.gz → 0.2.91__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.
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/PKG-INFO +2 -2
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/__init__.py +15 -1
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/app.py +72 -3
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/log/access_log_handler.py +8 -1
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/model/access_log.py +3 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/setting/__init__.py +24 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/setup/__init__.py +434 -9
- lesscode_flask-0.2.91/lesscode_flask/utils/fs_util.py +68 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/limit/req_count/count_limiter_handler.py +16 -16
- lesscode_flask-0.2.91/lesscode_flask/utils/sign/__init__.py +3 -0
- lesscode_flask-0.2.91/lesscode_flask/utils/sign/signature.py +160 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/swagger/swagger_util.py +113 -5
- lesscode_flask-0.2.91/lesscode_flask/utils/task/__init__.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask.egg-info/PKG-INFO +2 -2
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask.egg-info/SOURCES.txt +3 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask.egg-info/requires.txt +1 -1
- lesscode_flask-0.2.63/lesscode_flask/utils/fs_util.py +0 -55
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/README.md +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/db/__init__.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/db/datasource.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/db/executor.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/export_data/__init__.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/export_data/data_download_handler.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/model/base_model.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/model/parameterized_query.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/model/resource_param_template.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/model/response_result.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/model/user.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/model/user_limit_policy.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/service/access_log_service.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/service/base_service.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/service/resource_param_template_service.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/signals.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/static/swagger.py +0 -0
- {lesscode_flask-0.2.63/lesscode_flask/utils/decorator → lesscode_flask-0.2.91/lesscode_flask/utils}/__init__.py +0 -0
- {lesscode_flask-0.2.63/lesscode_flask/utils/task → lesscode_flask-0.2.91/lesscode_flask/utils/decorator}/__init__.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/decorator/cache.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/decorator/sql_injection.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/decorator/swagger.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/dify_utils.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/file/file_exporter.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/file/file_utils.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/helpers.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/json/NotSortJSONProvider.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/limit/__init__.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/limit/consecutive/consecutive_limiter_handler.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/limit/consecutive/redis_consecutive_limiter.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/limit/limit_util.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/limit/req/rate_limiter_handler.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/limit/req/redis_rate_limiter.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/limit/req_count/redis_count_limiter.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/oss/__init__.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/oss/aliyun_oss.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/oss/ks3_oss.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/oss/minio_oss.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/redis/redis_helper.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/request/request.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/swagger/swagger_template.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/task/task_helper.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/utils/thread/thread_utils.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask/wsgi.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask.egg-info/dependency_links.txt +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/lesscode_flask.egg-info/top_level.txt +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/redash/query_runner/__init__.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/redash/query_runner/clickhouse.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/redash/query_runner/elasticsearch.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/redash/query_runner/kingbase.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/redash/query_runner/mysql.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/redash/query_runner/pg.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/redash/settings/__init__.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/redash/settings/helpers.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/redash/utils/__init__.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/redash/utils/requests_session.py +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/setup.cfg +0 -0
- {lesscode_flask-0.2.63 → lesscode_flask-0.2.91}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lesscode-flask
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.91
|
|
4
4
|
Summary: lesscode-flask 是基于flask的web开发脚手架项目,该项目初衷为简化开发过程,让研发人员更加关注业务。
|
|
5
5
|
Home-page: https://lesscode-flask
|
|
6
6
|
Author: Chao.yy
|
|
@@ -11,7 +11,7 @@ Classifier: Operating System :: OS Independent
|
|
|
11
11
|
Requires-Python: >=3.9
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
Requires-Dist: Flask==3.0.3
|
|
14
|
-
Requires-Dist: lesscode-utils==0.0.
|
|
14
|
+
Requires-Dist: lesscode-utils==0.0.94
|
|
15
15
|
Requires-Dist: Flask-Login==0.6.3
|
|
16
16
|
Requires-Dist: redis==5.1.1
|
|
17
17
|
Requires-Dist: flask-swagger-ui==4.11.1
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
__version__ = "0.2.
|
|
1
|
+
__version__ = "0.2.91"
|
|
2
2
|
|
|
3
3
|
import functools
|
|
4
4
|
import logging
|
|
@@ -16,6 +16,20 @@ class SQ_Blueprint(Blueprint):
|
|
|
16
16
|
if not kwargs.get("import_name"):
|
|
17
17
|
kwargs["import_name"] = __name__
|
|
18
18
|
super().__init__(name=name, url_prefix=url_prefix, **kwargs)
|
|
19
|
+
# 记录蓝图内显式注册的“路径 + 方法”,供初始化阶段做冲突过滤。
|
|
20
|
+
self._route_method_keys = set()
|
|
21
|
+
|
|
22
|
+
def add_url_rule(self, rule, endpoint=None, view_func=None, provide_automatic_options=None, **options):
|
|
23
|
+
methods = options.get("methods")
|
|
24
|
+
if methods is None:
|
|
25
|
+
methods = ["GET"]
|
|
26
|
+
elif isinstance(methods, str):
|
|
27
|
+
methods = [methods]
|
|
28
|
+
methods = [str(item).upper() for item in methods if item]
|
|
29
|
+
for method in methods:
|
|
30
|
+
self._route_method_keys.add(f"{rule}|{method}")
|
|
31
|
+
return super().add_url_rule(rule, endpoint=endpoint, view_func=view_func,
|
|
32
|
+
provide_automatic_options=provide_automatic_options, **options)
|
|
19
33
|
|
|
20
34
|
def decorator_handler(
|
|
21
35
|
self,
|
|
@@ -18,7 +18,7 @@ from werkzeug.middleware.proxy_fix import ProxyFix
|
|
|
18
18
|
from lesscode_flask.model.response_result import ResponseResult
|
|
19
19
|
from lesscode_flask.setup import setup_blueprint, setup_logging, setup_query_runner, setup_swagger, setup_sql_alchemy, \
|
|
20
20
|
setup_redis, setup_login_manager, setup_resource_register, setup_data_download, setup_scheduler, \
|
|
21
|
-
setup_common_resource, setup_task
|
|
21
|
+
setup_common_resource, setup_task, setup_api_blueprint, prepare_api_blueprint_routes
|
|
22
22
|
from lesscode_flask.signals import app_runed
|
|
23
23
|
from lesscode_flask.utils.decorator.sql_injection import contains_sql_injection
|
|
24
24
|
from lesscode_flask.utils.helpers import inject_args, generate_uuid, app_config
|
|
@@ -31,6 +31,7 @@ from lesscode_flask.utils.limit.req.rate_limiter_handler import RateLimitHandler
|
|
|
31
31
|
from lesscode_flask.utils.limit.req_count.count_limiter_handler import CountLimitHandler
|
|
32
32
|
from lesscode_flask.utils.limit.req_count.redis_count_limiter import RedisCountLimiter
|
|
33
33
|
from lesscode_flask.utils.redis.redis_helper import RedisHelper
|
|
34
|
+
from lesscode_flask.utils.sign import verify_request_signature
|
|
34
35
|
from lesscode_flask.utils.swagger.swagger_util import generate_openapi_spec
|
|
35
36
|
|
|
36
37
|
# import collections.abc as cabc
|
|
@@ -74,6 +75,7 @@ class Lesscoder(Flask):
|
|
|
74
75
|
self.consecutiveAccessLimiter = RedisConsecutiveAccessLimiter(self.config.get("REDIS_LIMIT_KEY", "redis"))
|
|
75
76
|
|
|
76
77
|
def preprocess_request(self) -> ft.ResponseReturnValue | None:
|
|
78
|
+
verify_request_signature(self)
|
|
77
79
|
v = super(Lesscoder, self).preprocess_request()
|
|
78
80
|
user_limit_policy = None
|
|
79
81
|
if hasattr(self, 'countLimiter') and self.countLimiter:
|
|
@@ -164,7 +166,9 @@ class Lesscoder(Flask):
|
|
|
164
166
|
params_dict.update(view_args)
|
|
165
167
|
SQL_INJECTION_ENABLE = self.config.get("SQL_INJECTION_ENABLE", False)
|
|
166
168
|
if SQL_INJECTION_ENABLE:
|
|
167
|
-
|
|
169
|
+
sql_injection_white_list = self.config.get("SQL_INJECTION_WHITE_LIST", []) or []
|
|
170
|
+
is_sql_injection_white_path = any(req.path.startswith(path) for path in sql_injection_white_list)
|
|
171
|
+
if not is_sql_injection_white_path and contains_sql_injection(params_dict):
|
|
168
172
|
ResponseResult.fail("参数包含非法字符,请调整后重试!", status_code="403", http_code="403")
|
|
169
173
|
# 调用处理函数执行请求处理
|
|
170
174
|
result = self.ensure_sync(func)(**params_dict)
|
|
@@ -183,15 +187,80 @@ class Lesscoder(Flask):
|
|
|
183
187
|
return result
|
|
184
188
|
|
|
185
189
|
def setup(self):
|
|
190
|
+
def _collect_blueprint_route_method_keys(blueprint_map):
|
|
191
|
+
# 从项目内已定义的蓝图中提取“完整路径 + 方法”,用于后续排除同名自动接口。
|
|
192
|
+
route_method_keys = set()
|
|
193
|
+
for blueprint in blueprint_map.values():
|
|
194
|
+
prefix = (getattr(blueprint, "url_prefix", "") or "").rstrip("/")
|
|
195
|
+
# 优先使用 SQ_Blueprint 记录的路由元数据,避免依赖 Flask 闭包结构。
|
|
196
|
+
blueprint_keys = getattr(blueprint, "_route_method_keys", None)
|
|
197
|
+
if isinstance(blueprint_keys, set) and blueprint_keys:
|
|
198
|
+
for key in blueprint_keys:
|
|
199
|
+
if "|" not in key:
|
|
200
|
+
continue
|
|
201
|
+
route, method = key.rsplit("|", 1)
|
|
202
|
+
full_route = f"{prefix}{route}" if prefix else route
|
|
203
|
+
if not full_route.startswith("/"):
|
|
204
|
+
full_route = f"/{full_route}"
|
|
205
|
+
full_route = full_route.replace("//", "/")
|
|
206
|
+
route_method_keys.add(f"{full_route}|{str(method).upper()}")
|
|
207
|
+
continue
|
|
208
|
+
|
|
209
|
+
# 兜底方案:兼容普通 Blueprint 或未记录元数据的蓝图。
|
|
210
|
+
deferred_functions = getattr(blueprint, "deferred_functions", []) or []
|
|
211
|
+
for deferred in deferred_functions:
|
|
212
|
+
closure = getattr(deferred, "__closure__", None) or []
|
|
213
|
+
route = None
|
|
214
|
+
methods = None
|
|
215
|
+
for cell in closure:
|
|
216
|
+
value = cell.cell_contents
|
|
217
|
+
if isinstance(value, str) and value.startswith("/"):
|
|
218
|
+
route = value
|
|
219
|
+
elif isinstance(value, dict) and isinstance(value.get("methods"), (list, tuple, set)):
|
|
220
|
+
methods = [str(item).upper() for item in value.get("methods") if item]
|
|
221
|
+
if not route:
|
|
222
|
+
continue
|
|
223
|
+
full_route = f"{prefix}{route}" if prefix else route
|
|
224
|
+
if not full_route.startswith("/"):
|
|
225
|
+
full_route = f"/{full_route}"
|
|
226
|
+
full_route = full_route.replace("//", "/")
|
|
227
|
+
methods = methods or ["GET"]
|
|
228
|
+
for method in methods:
|
|
229
|
+
route_method_keys.add(f"{full_route}|{method}")
|
|
230
|
+
return route_method_keys
|
|
231
|
+
|
|
186
232
|
setup_logging(self)
|
|
233
|
+
# 1) 先从能力平台准备自动蓝图路由计划(仅组织数据,不立即注册)。
|
|
234
|
+
api_capability_server, api_route_prefix, api_route_list = prepare_api_blueprint_routes(self)
|
|
235
|
+
# 1) 先收集项目代码中的蓝图定义。
|
|
187
236
|
blueprint_map = setup_blueprint(self)
|
|
237
|
+
# 2) 用项目接口签名作为排除条件,确保同路径同方法时由项目接口覆盖自动接口。
|
|
238
|
+
project_route_method_keys = _collect_blueprint_route_method_keys(blueprint_map)
|
|
239
|
+
auto_blueprints = setup_api_blueprint(
|
|
240
|
+
self,
|
|
241
|
+
exclude_route_method_keys=project_route_method_keys,
|
|
242
|
+
existing_blueprint_names=set(blueprint_map.keys()),
|
|
243
|
+
route_list=api_route_list,
|
|
244
|
+
capability_server=api_capability_server,
|
|
245
|
+
route_prefix=api_route_prefix
|
|
246
|
+
)
|
|
188
247
|
setup_query_runner()
|
|
189
248
|
setup_swagger(self)
|
|
190
249
|
setup_sql_alchemy(self)
|
|
191
250
|
setup_redis(self)
|
|
192
251
|
setup_login_manager(self)
|
|
252
|
+
# 3) 先注册自动蓝图,再注册项目蓝图;同时自动蓝图已做冲突过滤,保证项目实现优先。
|
|
253
|
+
if auto_blueprints:
|
|
254
|
+
for auto_blueprint in auto_blueprints:
|
|
255
|
+
self.register_blueprint(
|
|
256
|
+
auto_blueprint,
|
|
257
|
+
name=getattr(auto_blueprint, "_registration_name", auto_blueprint.name)
|
|
258
|
+
)
|
|
193
259
|
for blueprint_name, blueprint in blueprint_map.items():
|
|
194
|
-
self.register_blueprint(
|
|
260
|
+
self.register_blueprint(
|
|
261
|
+
blueprint,
|
|
262
|
+
name=getattr(blueprint, "_registration_name", blueprint_name)
|
|
263
|
+
)
|
|
195
264
|
setup_common_resource(self)
|
|
196
265
|
setup_resource_register(self)
|
|
197
266
|
setup_data_download(self)
|
|
@@ -45,6 +45,12 @@ class AccessLogHandler(Handler):
|
|
|
45
45
|
app_key = request.headers.get("App-Key")
|
|
46
46
|
url = request.path
|
|
47
47
|
url_info_key = f"upms:url_info:{url}"
|
|
48
|
+
# 签名
|
|
49
|
+
signature = request.headers.get("signature") or request.headers.get('Signature')
|
|
50
|
+
# 随机数
|
|
51
|
+
nonce = request.headers.get("nonce") or request.headers.get('Nonce')
|
|
52
|
+
# 时间戳
|
|
53
|
+
timestamp = request.headers.get("timestamp") or request.headers.get('Timestamp')
|
|
48
54
|
|
|
49
55
|
resource_id = "-"
|
|
50
56
|
resource_label = url
|
|
@@ -66,7 +72,8 @@ class AccessLogHandler(Handler):
|
|
|
66
72
|
obj_id=current_user.id, type=current_user.type, client_id=client_id,
|
|
67
73
|
resource_id=resource_id, location=location, sub=current_user.sub,
|
|
68
74
|
resource_label=resource_label, url=url, referrer=referrer, client_ip=client_ip,
|
|
69
|
-
user_agent=user_agent_string, token=token, app_key=app_key,
|
|
75
|
+
user_agent=user_agent_string, token=token, app_key=app_key, signature=signature,
|
|
76
|
+
nonce=nonce, timestamp=timestamp, start_time=start_time,
|
|
70
77
|
end_time=end_time, duration=end_time - start_time, status_code=status_code,
|
|
71
78
|
params=params)
|
|
72
79
|
|
|
@@ -24,6 +24,9 @@ class AccessLog(BaseModel):
|
|
|
24
24
|
user_agent = Column(String(512), comment='客户端')
|
|
25
25
|
token = Column(String(64), comment='token')
|
|
26
26
|
app_key = Column(String(64), comment='请求的app_key')
|
|
27
|
+
signature = Column(String(64), comment='签名')
|
|
28
|
+
nonce = Column(String(64), comment='签名随机数')
|
|
29
|
+
timestamp = Column(String(64), comment='签名时间戳')
|
|
27
30
|
params = Column(JSONEncodedDict)
|
|
28
31
|
start_time = Column(DOUBLE, comment='开始时间')
|
|
29
32
|
end_time = Column(DOUBLE, comment='结束时间')
|
|
@@ -90,6 +90,22 @@ class BaseConfig:
|
|
|
90
90
|
AUTH_DEFAULT_ACCESS = 0
|
|
91
91
|
# 启用生成刷新token
|
|
92
92
|
OAUTH2_REFRESH_TOKEN_GENERATOR = True
|
|
93
|
+
# 请求签名校验开关(在token校验前执行)
|
|
94
|
+
SIGN_ENABLE: bool = False
|
|
95
|
+
# 固定签名密钥,建议在业务配置中覆盖
|
|
96
|
+
SIGN_SECRET: str = ""
|
|
97
|
+
# 签名有效时间窗口(秒)
|
|
98
|
+
SIGN_WINDOW_SEC: int = 300
|
|
99
|
+
# 防重放校验开关
|
|
100
|
+
SIGN_NONCE_ENABLE: bool = True
|
|
101
|
+
# nonce缓存时长(秒)
|
|
102
|
+
SIGN_NONCE_TTL_SEC: int = 300
|
|
103
|
+
# 签名白名单路径前缀
|
|
104
|
+
SIGN_WHITE_LIST: list = [SWAGGER_URL, SWAGGER_API_URL, f"{ROUTE_PREFIX}/oauth/token", f"{ROUTE_PREFIX}/oauth/captcha"]
|
|
105
|
+
# 签名IP白名单(支持单IP或CIDR,命中后跳过签名校验)
|
|
106
|
+
SIGN_IP_WHITE_LIST: list = []
|
|
107
|
+
# 忽略签名校验的方法
|
|
108
|
+
SIGN_IGNORE_METHODS: list = ["OPTIONS"]
|
|
93
109
|
# 是否启用限流频率验证
|
|
94
110
|
RATE_LIMIT_ENABLE: bool = False
|
|
95
111
|
|
|
@@ -132,6 +148,8 @@ class BaseConfig:
|
|
|
132
148
|
FS_OAM_SERVICE_URL = "https://oa.shangqi.com.cn"
|
|
133
149
|
# sql 注入验证器开关
|
|
134
150
|
SQL_INJECTION_ENABLE = False
|
|
151
|
+
# sql 注入检测白名单,命中路径前缀时跳过检测
|
|
152
|
+
SQL_INJECTION_WHITE_LIST: list = []
|
|
135
153
|
#
|
|
136
154
|
#
|
|
137
155
|
# # 外网地址
|
|
@@ -141,6 +159,9 @@ class BaseConfig:
|
|
|
141
159
|
#
|
|
142
160
|
# 数据服务
|
|
143
161
|
CAPABILITY_PLATFORM_SERVER: str = "http://127.0.0.1:8976"
|
|
162
|
+
# 转调能力平台时附加的自定义请求头(key/value 由业务配置覆盖)
|
|
163
|
+
DATA_SOURCE_KEY: str = "Data-Source-Id"
|
|
164
|
+
DATA_SOURCE_VALUE: str = ""
|
|
144
165
|
# # 权限服务地址
|
|
145
166
|
# OAUTH_SERVER: str = ""
|
|
146
167
|
# # 后端管理地址
|
|
@@ -165,6 +186,9 @@ class BaseConfig:
|
|
|
165
186
|
REGISTER_ENABLE = False
|
|
166
187
|
REGISTER_SERVER = "http://127.0.0.1:8976"
|
|
167
188
|
|
|
189
|
+
# 通过固定 API 拉取地址并自动注册蓝图(默认关闭)
|
|
190
|
+
AUTO_BLUEPRINT_ENABLE = False
|
|
191
|
+
|
|
168
192
|
# 本地环境
|
|
169
193
|
ENV = "local"
|
|
170
194
|
# 是否代理能力平台的公共接口
|