diff --git a/app.py b/app.py index f1a52350..6619ba39 100755 --- a/app.py +++ b/app.py @@ -192,17 +192,61 @@ es_client = Elasticsearch( ) app = Flask(__name__) -# 存储验证码的临时字典(生产环境应使用Redis) -verification_codes = {} -# ============ 微信登录 Session 管理(Redis 存储,支持多进程) ============ -# Redis 连接配置(支持环境变量覆盖,与 Flask-Session 共享配置) +# ============ Redis 连接配置(支持环境变量覆盖) ============ _REDIS_HOST = os.environ.get('REDIS_HOST', 'localhost') _REDIS_PORT = int(os.environ.get('REDIS_PORT', 6379)) redis_client = redis.Redis(host=_REDIS_HOST, port=_REDIS_PORT, db=0, decode_responses=True) +print(f"📦 Redis 配置: {_REDIS_HOST}:{_REDIS_PORT}/db=0") + +# ============ 验证码 Redis 存储(支持多进程/多 Worker) ============ +VERIFICATION_CODE_PREFIX = "vf_code:" +VERIFICATION_CODE_EXPIRE = 300 # 验证码过期时间(5分钟) + + +def set_verification_code(key, code, expires_in=VERIFICATION_CODE_EXPIRE): + """存储验证码到 Redis""" + try: + data = { + 'code': code, + 'expires': time.time() + expires_in + } + redis_client.setex( + f"{VERIFICATION_CODE_PREFIX}{key}", + expires_in, + json.dumps(data) + ) + return True + except Exception as e: + print(f"❌ Redis 存储验证码失败: {e}") + return False + + +def get_verification_code(key): + """从 Redis 获取验证码""" + try: + data = redis_client.get(f"{VERIFICATION_CODE_PREFIX}{key}") + if data: + return json.loads(data) + return None + except Exception as e: + print(f"❌ Redis 获取验证码失败: {e}") + return None + + +def delete_verification_code(key): + """从 Redis 删除验证码""" + try: + redis_client.delete(f"{VERIFICATION_CODE_PREFIX}{key}") + except Exception as e: + print(f"❌ Redis 删除验证码失败: {e}") + + +print(f"📦 验证码存储: Redis, 过期时间: {VERIFICATION_CODE_EXPIRE}秒") + +# ============ 微信登录 Session 管理(Redis 存储,支持多进程) ============ WECHAT_SESSION_EXPIRE = 300 # Session 过期时间(5分钟) WECHAT_SESSION_PREFIX = "wechat_session:" -print(f"📦 微信登录 Redis 配置: {_REDIS_HOST}:{_REDIS_PORT}/db=0") def set_wechat_session(state, data): @@ -3299,11 +3343,8 @@ def send_sms_verification(): # 发送短信 if send_sms_code(phone, code, SMS_TEMPLATE_REGISTER): - # 存储验证码(5分钟有效) - verification_codes[f'phone_{phone}'] = { - 'code': code, - 'expires': time.time() + 300 - } + # 存储验证码到 Redis(5分钟有效) + set_verification_code(f'phone_{phone}', code) return jsonify({'message': '验证码已发送'}), 200 else: return jsonify({'error': '验证码发送失败'}), 500 @@ -3326,11 +3367,8 @@ def send_email_verification(): # 发送邮件 if send_email_code(email, code): - # 存储验证码(5分钟有效) - verification_codes[f'email_{email}'] = { - 'code': code, - 'expires': time.time() + 300 - } + # 存储验证码到 Redis(5分钟有效) + set_verification_code(f'email_{email}', code) return jsonify({'message': '验证码已发送'}), 200 else: return jsonify({'error': '验证码发送失败'}), 500 @@ -3348,8 +3386,8 @@ def register_with_phone(): if not all([phone, code, password, username]): return jsonify({'success': False, 'error': '所有字段都是必填的'}), 400 - # 验证验证码 - stored_code = verification_codes.get(f'phone_{phone}') + # 验证验证码(从 Redis 获取) + stored_code = get_verification_code(f'phone_{phone}') if not stored_code or stored_code['expires'] < time.time(): return jsonify({'success': False, 'error': '验证码已过期'}), 400 @@ -3379,8 +3417,8 @@ def register_with_phone(): db.session.commit() - # 清除验证码 - del verification_codes[f'phone_{phone}'] + # 清除验证码(从 Redis 删除) + delete_verification_code(f'phone_{phone}') # 自动登录 session.permanent = True @@ -3423,10 +3461,8 @@ def send_sms_bind_code(): code = generate_verification_code() if send_sms_code(phone, code, SMS_TEMPLATE_REGISTER): - verification_codes[f'bind_{phone}'] = { - 'code': code, - 'expires': time.time() + 300 - } + # 存储验证码到 Redis(5分钟有效) + set_verification_code(f'bind_{phone}', code) return jsonify({'message': '验证码已发送'}), 200 else: return jsonify({'error': '验证码发送失败'}), 500 @@ -3445,7 +3481,8 @@ def bind_phone(): if not phone or not code: return jsonify({'error': '手机号和验证码不能为空'}), 400 - stored = verification_codes.get(f'bind_{phone}') + # 从 Redis 获取验证码 + stored = get_verification_code(f'bind_{phone}') if not stored or stored['expires'] < time.time(): return jsonify({'error': '验证码已过期'}), 400 if stored['code'] != code: @@ -3461,8 +3498,8 @@ def bind_phone(): user.phone = phone user.confirm_phone() - # 清除验证码 - del verification_codes[f'bind_{phone}'] + # 清除验证码(从 Redis 删除) + delete_verification_code(f'bind_{phone}') return jsonify({'message': '绑定成功', 'success': True}), 200 except Exception as e: @@ -3517,11 +3554,8 @@ def send_email_bind_code(): code = ''.join(random.choices(string.digits, k=6)) if send_email_code(email, code): - # 存储验证码(5分钟有效) - verification_codes[f'bind_{email}'] = { - 'code': code, - 'expires': time.time() + 300 - } + # 存储验证码到 Redis(5分钟有效) + set_verification_code(f'bind_{email}', code) return jsonify({'message': '验证码已发送'}), 200 else: return jsonify({'error': '验证码发送失败'}), 500 @@ -3540,7 +3574,8 @@ def bind_email(): if not email or not code: return jsonify({'error': '邮箱和验证码不能为空'}), 400 - stored = verification_codes.get(f'bind_{email}') + # 从 Redis 获取验证码 + stored = get_verification_code(f'bind_{email}') if not stored or stored['expires'] < time.time(): return jsonify({'error': '验证码已过期'}), 400 if stored['code'] != code: @@ -3558,8 +3593,8 @@ def bind_email(): user.confirm_email() db.session.commit() - # 清除验证码 - del verification_codes[f'bind_{email}'] + # 清除验证码(从 Redis 删除) + delete_verification_code(f'bind_{email}') return jsonify({ 'message': '邮箱绑定成功', @@ -3608,8 +3643,8 @@ def register_with_email(): if not all([email, code, password, username]): return jsonify({'success': False, 'error': '所有字段都是必填的'}), 400 - # 验证验证码 - stored_code = verification_codes.get(f'email_{email}') + # 验证验证码(从 Redis 获取) + stored_code = get_verification_code(f'email_{email}') if not stored_code or stored_code['expires'] < time.time(): return jsonify({'success': False, 'error': '验证码已过期'}), 400 @@ -3638,8 +3673,8 @@ def register_with_email(): db.session.commit() - # 清除验证码 - del verification_codes[f'email_{email}'] + # 清除验证码(从 Redis 删除) + delete_verification_code(f'email_{email}') # 自动登录 session.permanent = True