feat: 添加纯 Token 认证模式 (Token Only Mode)

- 新增 TOKEN_ONLY_MODE 配置项,支持跳过 HMAC 签名验证
- 纯 Token 模式下只验证 token 参数,简化配置
- 添加 TOKEN_ONLY_MODE.md 详细文档
- 设置页面显示当前模式状态
- 更新 README.md 说明新功能
- config.example.json 添加 token_only_mode 配置项

适用于 TranspondSms 不支持签名的场景。
This commit is contained in:
OpenClaw Agent
2026-02-07 00:55:46 +00:00
parent a308989c3b
commit 1d886ce68d
7 changed files with 376 additions and 7 deletions

42
app.py
View File

@@ -57,6 +57,7 @@ def create_app(config_name='default'):
app.config['LOGIN_USERNAME'] = app_config.LOGIN_USERNAME
app.config['LOGIN_PASSWORD'] = app_config.LOGIN_PASSWORD
app.config['SESSION_LIFETIME'] = app_config.SESSION_LIFETIME
app.config['TOKEN_ONLY_MODE'] = app_config.TOKEN_ONLY_MODE
# 初始化日志
setup_logging(app)
@@ -248,9 +249,11 @@ def register_routes(app, db):
def settings():
"""设置页面"""
return render_template('settings.html',
app={'name': '短信转发接收端'},
api_tokens=app.config['API_TOKENS'],
login_enabled=app.config['LOGIN_ENABLED'],
sign_verify=app.config['SIGN_VERIFY'])
sign_verify=app.config['SIGN_VERIFY'],
token_only_mode=app.config['TOKEN_ONLY_MODE'])
@app.route('/api/receive', methods=['POST'])
def receive_sms():
@@ -270,14 +273,37 @@ def register_routes(app, db):
'error', '缺少必填参数 (from/content)')
return jsonify({'error': '缺少必填参数'}), 400
# 如果提供了 token查找对应的 secret
# Token 验证
secret = None
if token_param:
token_valid = False
if app.config['TOKEN_ONLY_MODE']:
# 纯 Token 模式:只验证 token不需要签名
if not token_param:
db.add_log(from_number, content, None, sign, None, ip_address,
'error', '缺少 token 参数(纯 Token 模式已启用)')
return jsonify({'error': '缺少 token 参数'}), 401
for token_config in app.config['API_TOKENS']:
if token_config.get('enabled') and token_config.get('token') == token_param:
secret = token_config.get('secret')
token_valid = True
secret = token_config.get('secret', '')
app.logger.info(f'Token 验证成功: {token_param}')
break
if not token_valid:
db.add_log(from_number, content, None, sign, None, ip_address,
'error', f'Token 无效: {token_param}')
return jsonify({'error': 'Token 无效'}), 401
else:
# 标准 Token + 签名模式
if token_param:
for token_config in app.config['API_TOKENS']:
if token_config.get('enabled') and token_config.get('token') == token_param:
secret = token_config.get('secret')
break
# 解析时间戳
timestamp = None
if timestamp_str:
@@ -288,9 +314,9 @@ def register_routes(app, db):
'error', f'时间戳格式错误: {timestamp_str}')
return jsonify({'error': '时间戳格式错误'}), 400
# 验证签名
# 验证签名(仅在非纯 Token 模式且提供了 secret 时)
sign_verified = False
if sign and secret and app.config['SIGN_VERIFY']:
if not app.config['TOKEN_ONLY_MODE'] and sign and secret and app.config['SIGN_VERIFY']:
is_valid, message = verify_from_app(
from_number, content, timestamp, sign, secret,
app.config['SIGN_MAX_AGE']
@@ -305,6 +331,10 @@ def register_routes(app, db):
sign_verified = True
app.logger.info(f'短信已签名验证: {from_number}')
# 纯 Token 模式下token 验证成功则视为 sign_verified
if app.config['TOKEN_ONLY_MODE'] and token_valid:
sign_verified = True
# 保存短信
message_id = db.add_message(
from_number=from_number,