如何为游戏服务器指定路由配置Firebase身份验证?
基于Firebase Authentication实现Flask路由身份验证
1. 准备工作
- 安装依赖:
pip install firebase-admin - 从Firebase控制台下载服务账号密钥文件(JSON格式),放到项目根目录,命名为
firebase-service-account.json
2. 实现身份验证装饰器
编写Flask装饰器,用于校验请求中的Firebase ID令牌,保护需要权限的路由:
def require_auth(f): @wraps(f) def decorated(*args, **kwargs): auth_header = request.headers.get('Authorization') if not auth_header or not auth_header.startswith('Bearer '): return jsonify({'error': '缺少有效身份验证令牌'}), 401 id_token = auth_header.split('Bearer ')[1] try: # 验证令牌有效性,自动处理过期、签名校验等逻辑 decoded_token = auth.verify_id_token(id_token) # 将用户信息挂载到request对象,供路由函数使用(可选) request.user = decoded_token return f(*args, **kwargs) except auth.InvalidIdTokenError: return jsonify({'error': '无效的身份验证令牌'}), 401 except auth.ExpiredIdTokenError: return jsonify({'error': '身份验证令牌已过期'}), 401 except Exception as e: return jsonify({'error': f'身份验证失败: {str(e)}'}), 401 return decorated
3. 完整改造后的代码
将装饰器应用到需要验证的路由,并完成Firebase Admin SDK初始化:
from flask import Flask, request, jsonify import firebase_admin from firebase_admin import auth, credentials from functools import wraps # 初始化Firebase Admin SDK cred = credentials.Certificate('firebase-service-account.json') firebase_admin.initialize_app(cred) app = Flask(__name__) # 身份验证装饰器 def require_auth(f): @wraps(f) def decorated(*args, **kwargs): auth_header = request.headers.get('Authorization') if not auth_header or not auth_header.startswith('Bearer '): return jsonify({'error': '缺少有效身份验证令牌'}), 401 id_token = auth_header.split('Bearer ')[1] try: decoded_token = auth.verify_id_token(id_token) request.user = decoded_token return f(*args, **kwargs) except auth.InvalidIdTokenError: return jsonify({'error': '无效的身份验证令牌'}), 401 except auth.ExpiredIdTokenError: return jsonify({'error': '身份验证令牌已过期'}), 401 except Exception as e: return jsonify({'error': f'身份验证失败: {str(e)}'}), 401 return decorated # 公开路由:无需验证即可访问 @app.route("/entries") def entries(): return jsonify(firebase.get_entries()) @app.route("/entries/<string:id>") def entry(id): return jsonify(firebase.get_entry(id)) @app.route("/entries/<string:id>/<string:property>") def entry_property(id, property): entry_data = firebase.get_entry(id) if property in entry_data: return jsonify({property: entry_data[property]}) return jsonify({'error': '属性不存在'}), 404 # 受保护路由:创建条目需验证身份 @app.route("/create_entry/<string:id>", methods=['GET']) @require_auth def create_entry(id): try: name = request.args.get("name") description = request.args.get("description") if not name or not description: return jsonify({'error': 'name和description参数不能为空'}), 400 entry = { "name": name, "description": description, "created_by": request.user['uid'] # 可选:记录创建者UID } e = firebase.create_entry(id, entry) if e: return jsonify({'message': str(e)}) return jsonify({'message': f'已创建ID为{id}的条目'}) except Exception as e: return jsonify({'error': str(e)}), 500 # 移除末尾斜杠 @app.before_request def trailing(): rp = request.path if rp != '/' and rp.endswith('/'): return jsonify({'error': '请勿使用末尾斜杠,示例: /entries,而非/entries/'}), 404 if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=True)
关键说明
- 客户端请求受保护路由时,需在请求头中携带
Authorization: Bearer <Firebase_ID_TOKEN> - 验证通过后,解码的用户信息(如UID、邮箱等)会存入
request.user,可在路由中直接调用 - 生产环境建议将
create_entry改为POST方法,通过请求体传递参数而非URL参数 - 确保
firebase模块中的get_entries、get_entry、create_entry方法已正确实现与Firebase数据库的交互
内容的提问来源于stack exchange,提问作者Possible Panda
相关产品推荐
相关产品推荐

