You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Django Rest Framework中创建会话及Firebase认证对接技术问询

Django Rest Framework 结合 Firebase 身份认证实现方案

我之前刚好做过DRF结合Firebase做身份认证的需求,和你的场景完全匹配——前端走Firebase登录,把令牌传给后端验证,通过后关联本地用户。下面把我实际实现的步骤整理给你:

1. 编写自定义Firebase认证类

首先得实现一个继承DRF BaseAuthentication 的自定义认证类,专门处理请求头里的tokenid验证逻辑:

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
import firebase_admin
from firebase_admin import auth, credentials

# 初始化Firebase Admin(建议把这段放到项目settings.py或者单独的配置文件里,避免重复初始化)
cred = credentials.Certificate("path/to/your/firebase-service-account.json")
firebase_admin.initialize_app(cred)

class FirebaseAuthentication(BaseAuthentication):
    def authenticate(self, request):
        # DRF会把自定义请求头转为大写并加上HTTP_前缀,所以这里取HTTP_TOKENID
        token = request.META.get('HTTP_TOKENID')
        if not token:
            return None  # 没有令牌就不触发认证,后续权限控制会处理未认证的请求
        
        try:
            # 调用Firebase Admin的接口验证令牌有效性
            decoded_token = auth.verify_id_token(token)
            # 从解码后的令牌里取出Firebase用户的uid
            firebase_uid = decoded_token['uid']
            
            # 根据Firebase的uid关联本地数据库的用户实例
            # 这里假设你的用户模型是CustomUser,记得提前给模型加firebase_uid字段(唯一约束)
            from .models import CustomUser
            user = CustomUser.objects.get(firebase_uid=firebase_uid)
            
            # DRF认证类要求返回(用户实例, None)的格式
            return (user, None)
        
        # 捕获常见的令牌错误,返回清晰的认证失败信息
        except auth.InvalidIdTokenError:
            raise AuthenticationFailed("无效的Firebase令牌")
        except auth.ExpiredIdTokenError:
            raise AuthenticationFailed("Firebase令牌已过期")
        except CustomUser.DoesNotExist:
            raise AuthenticationFailed("未找到关联的本地用户")
        except Exception as e:
            raise AuthenticationFailed(f"认证失败: {str(e)}")

这里几个关键点要注意:

  • 一定要处理HTTP_TOKENID请求头,因为DRF会自动把前端传的tokenid转成这个格式
  • 验证令牌时要捕获Firebase抛出的特定异常,给前端返回明确的错误提示
  • 必须返回(user, None),这是DRF认证类的规范,这样request.user才能正确拿到用户实例

2. 实现/login路由的视图

接下来写一个绑定/login路由的视图,用来处理前端的登录请求:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import AllowAny
from .authentication import FirebaseAuthentication

class LoginView(APIView):
    # 登录接口允许匿名访问,所以设置AllowAny权限
    permission_classes = [AllowAny]
    # 指定用我们刚才写的Firebase认证类处理这个请求的认证
    authentication_classes = [FirebaseAuthentication]

    def post(self, request):
        # 认证通过后,request.user就是我们本地数据库的用户实例了
        # 这里可以返回用户基本信息,或者生成DRF自己的令牌(比如用simplejwt)给前端后续请求用
        return Response({
            "code": 200,
            "message": "登录成功",
            "user_info": {
                "id": request.user.id,
                "username": request.user.username,
                "email": request.user.email
            }
        })

这个视图的逻辑很清晰:

  • 因为是登录接口,必须允许匿名访问,所以设置permission_classes=[AllowAny]
  • 指定authentication_classes后,请求进来时会自动触发Firebase令牌验证
  • 验证通过后直接返回用户信息,或者如果需要用DRF自身的认证体系,可以在这里生成并返回JWT令牌

3. 可选:全局配置认证类

如果你的项目大部分接口都需要Firebase认证,可以直接在settings.py里全局配置,这样不用每个视图都手动指定认证类:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'your_app_name.authentication.FirebaseAuthentication',
        # 可以保留DRF默认的Session认证,方便后台管理使用
        'rest_framework.authentication.SessionAuthentication',
    ],
}

这样全局配置后,只有少数特殊接口(比如登录)可以单独覆盖authentication_classes或者permission_classes。

额外注意事项

  • 不要硬编码Firebase服务账号的路径,建议用环境变量来配置,比如os.environ.get('FIREBASE_SERVICE_ACCOUNT_PATH')
  • 本地用户模型一定要添加firebase_uid字段,类型用CharField,并设置unique=True,确保一个Firebase用户只关联一个本地用户
  • 前端发送请求时,要把Firebase登录后拿到的idToken放到tokenid请求头里,不要写错字段名

内容的提问来源于stack exchange,提问作者Ben Gosub

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 09:12:53