v0-json-schema
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
id: authentication-headers-required
|
||||
name: API认证头部要求规则
|
||||
description: 验证API请求是否包含必要的认证头部,如Authorization、X-API-Key等
|
||||
category: Security
|
||||
version: 1.0.0
|
||||
severity: error
|
||||
is_enabled: true
|
||||
tags:
|
||||
- security
|
||||
- authentication
|
||||
- headers
|
||||
- authorization
|
||||
target_type: APIRequest
|
||||
lifecycle: RequestPreparation
|
||||
scope: RequestHeaders
|
||||
required_headers:
|
||||
- name: Authorization
|
||||
pattern: "^(Bearer|Basic|Digest) [A-Za-z0-9\\-\\._~\\+\\/]+=*$"
|
||||
description: 认证令牌,格式应为"Bearer token"、"Basic base64"或"Digest value"
|
||||
- name: X-API-Key
|
||||
pattern: "^[A-Za-z0-9]{32,64}$"
|
||||
description: API密钥,应为32-64位的字母数字字符
|
||||
- name: X-Request-ID
|
||||
pattern: "^[A-Za-z0-9\\-]{8,36}$"
|
||||
description: 请求ID,用于跟踪请求,应为8-36位的字母数字和连字符
|
||||
check_mode: any # 可以是"all"或"any",表示是需要满足所有头部还是任一头部
|
||||
code: |
|
||||
def validate(context):
|
||||
"""验证API请求是否包含必要的认证头部"""
|
||||
request = context.get('api_request')
|
||||
if not request:
|
||||
return {'is_valid': False, 'message': '缺少API请求对象'}
|
||||
|
||||
headers = request.headers or {}
|
||||
required_headers = context.get('required_headers', [])
|
||||
check_mode = context.get('check_mode', 'any')
|
||||
|
||||
# 获取缺失的头部和无效的头部
|
||||
missing_headers = []
|
||||
invalid_headers = []
|
||||
valid_headers = []
|
||||
|
||||
import re
|
||||
|
||||
for header in required_headers:
|
||||
header_name = header.get('name')
|
||||
header_pattern = header.get('pattern')
|
||||
|
||||
if header_name not in headers:
|
||||
missing_headers.append({
|
||||
'name': header_name,
|
||||
'description': header.get('description', '')
|
||||
})
|
||||
continue
|
||||
|
||||
header_value = headers[header_name]
|
||||
|
||||
# 如果指定了模式,验证头部值是否符合模式
|
||||
if header_pattern and not re.match(header_pattern, header_value):
|
||||
invalid_headers.append({
|
||||
'name': header_name,
|
||||
'value': header_value,
|
||||
'pattern': header_pattern,
|
||||
'description': header.get('description', '')
|
||||
})
|
||||
else:
|
||||
valid_headers.append(header_name)
|
||||
|
||||
# 根据检查模式判断是否验证通过
|
||||
if check_mode == 'all':
|
||||
# 需要所有头部都存在且有效
|
||||
is_valid = not missing_headers and not invalid_headers
|
||||
else: # 'any'
|
||||
# 至少有一个有效的头部即可
|
||||
is_valid = len(valid_headers) > 0
|
||||
|
||||
if is_valid:
|
||||
message = '请求包含有效的认证头部'
|
||||
if check_mode == 'any':
|
||||
message += f": {', '.join(valid_headers)}"
|
||||
else:
|
||||
if check_mode == 'all':
|
||||
if missing_headers:
|
||||
message = f"请求缺少必要的认证头部: {', '.join([h['name'] for h in missing_headers])}"
|
||||
else:
|
||||
message = f"请求包含无效的认证头部: {', '.join([h['name'] for h in invalid_headers])}"
|
||||
else: # 'any'
|
||||
message = f"请求不包含任何有效的认证头部,至少需要其中之一: {', '.join([h['name'] for h in required_headers])}"
|
||||
|
||||
return {
|
||||
'is_valid': is_valid,
|
||||
'message': message,
|
||||
'details': {
|
||||
'check_mode': check_mode,
|
||||
'valid_headers': valid_headers,
|
||||
'missing_headers': missing_headers,
|
||||
'invalid_headers': invalid_headers
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
id: standard-error-response
|
||||
name: 标准错误响应格式规则
|
||||
description: 验证API错误响应是否符合标准格式
|
||||
category: ErrorHandling
|
||||
version: 1.0.0
|
||||
severity: warning
|
||||
is_enabled: true
|
||||
tags:
|
||||
- error-handling
|
||||
- response-format
|
||||
target_type: APIResponse
|
||||
lifecycle: ResponseValidation
|
||||
scope: ResponseBody
|
||||
error_code: "*" # 匹配所有错误码
|
||||
expected_status: -1 # 不验证状态码
|
||||
code: |
|
||||
def validate(context):
|
||||
response = context.get('api_response')
|
||||
if not response:
|
||||
return {'is_valid': False, 'message': '缺少API响应对象'}
|
||||
|
||||
# 只检查4xx和5xx状态码的响应
|
||||
if response.status_code < 400:
|
||||
return {'is_valid': True, 'message': '非错误响应,跳过验证'}
|
||||
|
||||
# 确保响应包含JSON内容
|
||||
if not response.json_content:
|
||||
return {
|
||||
'is_valid': False,
|
||||
'message': '错误响应不是有效的JSON格式',
|
||||
'details': {
|
||||
'status_code': response.status_code,
|
||||
'content_type': response.headers.get('Content-Type', '未知')
|
||||
}
|
||||
}
|
||||
|
||||
# 检查错误响应的必要字段
|
||||
required_fields = ['code', 'message']
|
||||
missing_fields = [field for field in required_fields if field not in response.json_content]
|
||||
|
||||
if missing_fields:
|
||||
return {
|
||||
'is_valid': False,
|
||||
'message': '错误响应缺少必要字段',
|
||||
'details': {
|
||||
'missing_fields': missing_fields,
|
||||
'required_fields': required_fields,
|
||||
'response': response.json_content
|
||||
}
|
||||
}
|
||||
|
||||
# 检查字段类型
|
||||
if not isinstance(response.json_content.get('code'), (str, int)):
|
||||
return {
|
||||
'is_valid': False,
|
||||
'message': '错误码字段类型不正确',
|
||||
'details': {
|
||||
'field': 'code',
|
||||
'expected_type': 'string或integer',
|
||||
'actual_type': type(response.json_content.get('code')).__name__
|
||||
}
|
||||
}
|
||||
|
||||
if not isinstance(response.json_content.get('message'), str):
|
||||
return {
|
||||
'is_valid': False,
|
||||
'message': '错误消息字段类型不正确',
|
||||
'details': {
|
||||
'field': 'message',
|
||||
'expected_type': 'string',
|
||||
'actual_type': type(response.json_content.get('message')).__name__
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
'is_valid': True,
|
||||
'message': '错误响应符合标准格式',
|
||||
'details': {
|
||||
'status_code': response.status_code,
|
||||
'error_code': response.json_content.get('code'),
|
||||
'error_message': response.json_content.get('message')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
id: response-time-threshold
|
||||
name: 响应时间阈值规则
|
||||
description: 验证API响应时间是否在允许的范围内
|
||||
category: Performance
|
||||
version: 1.0.0
|
||||
severity: warning
|
||||
is_enabled: true
|
||||
tags:
|
||||
- performance
|
||||
- response-time
|
||||
target_type: APIResponse
|
||||
lifecycle: ResponseValidation
|
||||
scope: ResponseTime
|
||||
threshold: 500 # 毫秒
|
||||
metric: response_time
|
||||
unit: ms
|
||||
code: |
|
||||
def validate(context):
|
||||
response = context.get('api_response')
|
||||
if not response:
|
||||
return {'is_valid': False, 'message': '缺少API响应对象'}
|
||||
|
||||
response_time = response.elapsed_time * 1000 # 转换为毫秒
|
||||
threshold = context.get('threshold', 500) # 默认500毫秒
|
||||
|
||||
if response_time > threshold:
|
||||
return {
|
||||
'is_valid': False,
|
||||
'message': f'响应时间 {response_time:.2f}ms 超过阈值 {threshold}ms',
|
||||
'details': {
|
||||
'actual_time': response_time,
|
||||
'threshold': threshold,
|
||||
'unit': 'ms'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
'is_valid': True,
|
||||
'message': f'响应时间 {response_time:.2f}ms 在阈值 {threshold}ms 内',
|
||||
'details': {
|
||||
'actual_time': response_time,
|
||||
'threshold': threshold,
|
||||
'unit': 'ms'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
id: restful-url-pattern
|
||||
name: RESTful URL设计规则
|
||||
description: 验证API URL是否符合RESTful设计规范
|
||||
category: APIDesign
|
||||
version: 1.0.0
|
||||
severity: warning
|
||||
is_enabled: true
|
||||
tags:
|
||||
- restful
|
||||
- api-design
|
||||
- url-pattern
|
||||
target_type: APIRequest
|
||||
lifecycle: RequestPreparation
|
||||
scope: RequestURL
|
||||
design_aspect: URL设计
|
||||
pattern: "^/api/v\\d+/[a-z0-9-]+(/[a-z0-9-]+)*$"
|
||||
code: |
|
||||
import re
|
||||
|
||||
def validate(context):
|
||||
request = context.get('api_request')
|
||||
if not request:
|
||||
return {'is_valid': False, 'message': '缺少API请求对象'}
|
||||
|
||||
url = str(request.url)
|
||||
|
||||
# 解析URL,获取路径部分
|
||||
from urllib.parse import urlparse
|
||||
parsed_url = urlparse(url)
|
||||
path = parsed_url.path
|
||||
|
||||
# 使用正则表达式验证路径
|
||||
pattern = context.get('pattern', "^/api/v\\d+/[a-z0-9-]+(/[a-z0-9-]+)*$")
|
||||
if not re.match(pattern, path):
|
||||
return {
|
||||
'is_valid': False,
|
||||
'message': 'API URL不符合RESTful设计规范',
|
||||
'details': {
|
||||
'current_path': path,
|
||||
'expected_pattern': pattern,
|
||||
'suggestion': '路径应该遵循 /api/v{version}/{资源}[/{id}] 格式'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
'is_valid': True,
|
||||
'message': 'API URL符合RESTful设计规范',
|
||||
'details': {
|
||||
'path': path
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
id: https-only-rule
|
||||
name: HTTPS强制使用规则
|
||||
description: 验证API是否只使用HTTPS协议,确保通信安全
|
||||
category: Security
|
||||
version: 1.0.0
|
||||
severity: error
|
||||
is_enabled: true
|
||||
tags:
|
||||
- security
|
||||
- https
|
||||
- encryption
|
||||
target_type: APIRequest
|
||||
lifecycle: RequestPreparation
|
||||
scope: Security
|
||||
check_type: transport_security
|
||||
expected_value: https
|
||||
code: |
|
||||
def validate(context):
|
||||
request = context.get('api_request')
|
||||
if not request:
|
||||
return {'is_valid': False, 'message': '缺少API请求对象'}
|
||||
|
||||
url = str(request.url)
|
||||
|
||||
if not url.startswith('https://'):
|
||||
return {
|
||||
'is_valid': False,
|
||||
'message': 'API请求必须使用HTTPS协议',
|
||||
'details': {
|
||||
'current_url': url,
|
||||
'expected_protocol': 'https'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
'is_valid': True,
|
||||
'message': 'API请求使用了HTTPS协议',
|
||||
'details': {
|
||||
'url': url
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user