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:
42
app.py
42
app.py
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user