如何集成Firebase手机认证与Django后端实现用户同步及API鉴权
实现方案
首先提前安装所需依赖:
pip install djangorestframework firebase-admin
需求1:Firebase注册自动同步Django用户
- 第一步:改造Django用户模型,以Firebase UID作为用户唯一标识,同时新增你需要的扩展字段。你可以直接扩展Django自带的
AbstractUser,也可以用一对一关联的独立用户资料表,以下是直接扩展的示例:
# 你的应用/models.py from django.contrib.auth.models import AbstractUser from django.db import models class CustomUser(AbstractUser): firebase_uid = models.CharField(max_length=128, unique=True, null=False, blank=False) avatar_url = models.URLField(blank=True) address = models.TextField(blank=True) # 其他需要的扩展字段(订单、支付记录建议单独建表关联用户)
修改完成后在settings.py中指定自定义用户模型,再执行python manage.py makemigrations和python manage.py migrate完成数据库迁移:
# settings.py AUTH_USER_MODEL = '你的应用名.CustomUser'
- 第二步:编写用户同步接口,接口内部先校验Firebase凭证合法性,再同步创建或更新用户:
# 你的应用/views.py from rest_framework import status from rest_framework.response import Response from rest_framework.views import APIView from rest_framework.permissions import AllowAny from firebase_admin import auth from .models import CustomUser class SyncFirebaseUserView(APIView): permission_classes = [AllowAny] def post(self, request): id_token = request.data.get("id_token") # 校验Firebase凭证合法性,防止恶意调用 try: decoded_token = auth.verify_id_token(id_token) firebase_uid = decoded_token["uid"] email = decoded_token.get("email", "") display_name = decoded_token.get("name", "") except Exception as e: return Response({"error": "无效的认证凭证"}, status=status.HTTP_401_UNAUTHORIZED) # 同步用户,已存在的用户直接返回信息不重复创建 user, created = CustomUser.objects.get_or_create( firebase_uid=firebase_uid, defaults={ "email": email, "username": firebase_uid, "first_name": display_name } ) return Response({"user_id": user.id, "firebase_uid": firebase_uid}, status=status.HTTP_200_OK)
记得把这个接口加到路由配置里。
- 第三步:Flutter端用户完成Firebase注册后,立刻调用上述同步接口:
// Flutter 注册成功后调用示例 import 'package:firebase_auth/firebase_auth.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; Future<void> syncUserToDjango() async { User? currentUser = FirebaseAuth.instance.currentUser; if (currentUser != null) { String? idToken = await currentUser.getIdToken(); await http.post( Uri.parse("你的Django服务地址/api/sync-firebase-user/"), headers: {"Content-Type": "application/json"}, body: jsonEncode({"id_token": idToken}), ); } }
需求2:Django接口校验Firebase认证状态
- 第一步:Django项目初始化Firebase Admin SDK,先从Firebase控制台下载服务账号JSON文件放到项目根目录,然后在项目根目录的
__init__.py中添加初始化代码:
# 项目根目录/__init__.py import firebase_admin from firebase_admin import credentials import os if not firebase_admin._apps: cred = credentials.Certificate(os.path.join(os.path.dirname(__file__), "你的服务账号文件名.json")) firebase_admin.initialize_app(cred)
- 第二步:编写DRF自定义认证类,自动校验请求携带的Firebase凭证:
# 你的应用/authentication.py from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from firebase_admin import auth from .models import CustomUser class FirebaseAuthentication(BaseAuthentication): def authenticate(self, request): auth_header = request.META.get("HTTP_AUTHORIZATION") # 没有携带认证头的请求直接跳过 if not auth_header or not auth_header.startswith("Bearer "): return None id_token = auth_header.split(" ")[1] try: decoded_token = auth.verify_id_token(id_token) firebase_uid = decoded_token["uid"] except Exception as e: raise AuthenticationFailed("认证凭证无效或已过期") try: user = CustomUser.objects.get(firebase_uid=firebase_uid) except CustomUser.DoesNotExist: raise AuthenticationFailed("用户未同步到系统") return (user, None)
- 第三步:配置DRF默认使用该认证类,也可以给需要的接口单独指定:
# settings.py REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ '你的应用名.authentication.FirebaseAuthentication', ], 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', # 全局接口默认需要认证,不需要认证的接口单独设置permission_classes = [AllowAny] ] }
- 第四步:Flutter端所有请求Django接口时,在请求头携带Firebase id token即可:
// Flutter 请求示例 Future<void> fetchUserInfo() async { User? currentUser = FirebaseAuth.instance.currentUser; if (currentUser != null) { String? idToken = await currentUser.getIdToken(); var response = await http.get( Uri.parse("你的Django服务地址/api/user/info/"), headers: { "Content-Type": "application/json", "Authorization": "Bearer $idToken" }, ); // 处理返回结果 } }
注意事项
- Firebase的id token默认有效期1小时,Flutter的
getIdToken()方法会自动刷新过期的token,不需要手动处理刷新逻辑 - 如果用户在Firebase端被禁用、注销,Django侧校验token时会直接返回认证失败,符合安全要求
- 同步用户接口支持重复调用,不会出现重复创建用户的问题
内容的提问来源于stack exchange,提问作者erbibek
相关产品推荐
相关产品推荐

