Firebase Auth JS搭配Flask时如何传递登录token实现页面访问控制
核心问题解答
你需要将Firebase生成的ID token发送到Flask服务端。因为home.html是受保护资源,仅靠客户端的登录状态无法保证服务端路由的安全性,必须由服务端校验token的合法性后,再决定是否返回受保护页面或者放行访问。
完整实现步骤
第一步:修改前端登录逻辑,登录成功后获取并传递token
调整原有登录JS代码,在Firebase登录成功的回调中获取ID token,再将token发送到Flask后端校验:
btnSignIn.addEventListener('click', e => { // Get email/pass const email = inputEmail.value; const pass = inputPassword.value; /* to-do some validation and then sign in */ // Sign in firebase.auth().signInWithEmailAndPassword(email, pass) .then(userCredential => { // 登录成功,获取ID token return userCredential.user.getIdToken(/* forceRefresh */ true) }) .then(idToken => { // 方案1:将token存在localStorage,后续所有请求手动携带 localStorage.setItem('firebaseIdToken', idToken); // 方案2:将token存在Cookie,跳转后服务端可直接读取,无需手动携带 document.cookie = `firebaseIdToken=${idToken}; path=/; secure; SameSite=Strict`; // 校验通过后跳转到受保护页 window.location.href = '/home'; }) .catch(e => console.log(e.message)) });
第二步:Flask端安装依赖并实现token校验逻辑
首先安装Firebase Admin SDK用于token校验:pip install firebase-admin
之后去Firebase控制台下载你的项目服务账号密钥JSON文件,放到Flask项目目录下,再编写校验逻辑:
import firebase_admin from firebase_admin import auth, credentials from flask import request, redirect, render_template, url_for # 初始化Firebase Admin SDK,*替换成你自己的服务账号密钥文件路径* cred = credentials.Certificate("path/to/your/serviceAccountKey.json") firebase_admin.initialize_app(cred) # 登录校验装饰器,所有受保护路由都可以挂载这个装饰器 def login_required(f): def wrap(*args, **kwargs): id_token = None # 优先从Cookie读取token,也可以适配从请求头读取的逻辑 id_token = request.cookies.get('firebaseIdToken') # 如果用请求头传token的话用下面的逻辑 # if 'Authorization' in request.headers: # auth_header = request.headers['Authorization'] # if auth_header.startswith('Bearer '): # id_token = auth_header.split(' ')[1] if not id_token: # 无token直接跳转到登录页 return redirect(url_for('login')) try: # 校验token合法性,过期、伪造的token都会触发异常 decoded_token = auth.verify_id_token(id_token) # 可将解析出的用户信息存入request,供后续路由逻辑使用 request.user = decoded_token except Exception as e: # token无效,清空无效Cookie并跳登录 resp = redirect(url_for('login')) resp.set_cookie('firebaseIdToken', '', expires=0) return resp return f(*args, **kwargs) wrap.__name__ = f.__name__ return wrap
第三步:修改Flask路由,给受保护页面加校验
@app.route('/') @app.route('/home') @login_required def home(): # 走到这里已经通过token校验,直接返回受保护页面 return render_template("home.html") @app.route('/login', methods=['GET', 'POST']) def login(): # 已登录用户访问登录页可直接跳转到首页,可选优化 id_token = request.cookies.get('firebaseIdToken') if id_token: try: auth.verify_id_token(id_token) return redirect(url_for('home')) except: pass return render_template("login.html")
可选优化点
- 客户端监听Firebase的
onAuthStateChanged事件,token过期时自动刷新更新Cookie - 生产环境必须使用HTTPS传输token,避免token被窃取
- 登出逻辑里记得清空存储的token和Cookie
内容的提问来源于stack exchange,提问作者CaioT
相关产品推荐
相关产品推荐

