You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Firebase与Django Rest验证ID Token及对接认证?

Firebase Auth 对接 Django REST 后端完整流程解析&问题解决

我来一步步帮你理清整个流程,解决你遇到的核心疑问:

一、先搞懂整体认证链路

整个流程的核心是用Firebase的ID Token作为前后端的认证凭证,完整链路是:

  1. 前端调用Firebase原生登录接口完成身份验证,拿到用户对象
  2. 前端从用户对象中获取Firebase签发的ID Token
  3. 前端带着这个Token请求Django后端接口(作为身份凭证)
  4. 后端用Firebase Admin SDK验证Token合法性
  5. 验证通过后,后端可关联Django本地用户(可选),返回业务数据或授权凭证

二、前端代码的两处修正

你的前端代码有两个关键问题,修正后就能解决部分报错:

async login() { 
  this.error = null; 
  try { 
    const response = await firebase.auth().signInWithEmailAndPassword(this.email, this.password); 
    const tokenResult = await response.user.getIdTokenResult(); 
    // 1. 获取Django默认设置的CSRF Token(从cookie中读取)
    const csrfToken = document.cookie.split('; ').find(row => row.startsWith('csrftoken='))?.split('=')[1];
    
    fetch("/api/verify-firebase-token/", { 
      method: "POST", 
      headers: { 
        "Content-Type": "application/json",
        // 2. 修正Authorization头格式:DRF默认识别Bearer Token规范
        "Authorization": `Bearer ${tokenResult.token}`, 
        "X-CSRFToken": csrfToken // 带上CSRF Token解决403错误
      },
      // 这里不需要再传密码了!Firebase已经验证过身份,后端只需要Token
      body: JSON.stringify({ uid: tokenResult.uid }) 
    }).then((response) => response.json().then((data) => {
      console.log(data);
      // 验证通过后,后续所有API请求都可以带上这个Authorization头
    })); 
  } catch (error) { 
    this.error = error; 
  } 
}, 

三、后端:verify_id_token该放哪里?

verify_id_token需要封装在自定义认证类里,用来自动验证前端传来的Token。这个类是Django REST Framework的认证扩展,步骤如下:

1. 安装并初始化Firebase Admin SDK

先安装依赖:

pip install firebase-admin

然后在项目中初始化Firebase(比如新建myapp/firebase.py):

import firebase_admin
from firebase_admin import credentials, auth

# 替换为你的Firebase服务账号密钥路径
cred = credentials.Certificate("path/to/serviceAccountKey.json")
firebase_admin.initialize_app(cred)

2. 编写自定义认证类

新建myapp/authentication.py

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from firebase_admin import auth
from .firebase import *

class FirebaseAuthentication(BaseAuthentication):
    def authenticate(self, request):
        # 从请求头中提取Token
        auth_header = request.headers.get('Authorization')
        if not auth_header or not auth_header.startswith('Bearer '):
            return None  # 无Token则交给其他认证类处理

        id_token = auth_header.split('Bearer ')[1]
        
        try:
            # 验证Token合法性
            decoded_token = auth.verify_id_token(id_token)
            uid = decoded_token['uid']
            # 可选:关联Django本地用户(比如根据uid查找或创建User)
            # from django.contrib.auth.models import User
            # user, created = User.objects.get_or_create(username=uid)
            # 返回(user, None),DRF会自动把user绑定到request.user
            return (uid, None)
        except auth.InvalidIdTokenError:
            raise AuthenticationFailed('无效的Firebase Token')
        except Exception as e:
            raise AuthenticationFailed(f'Token验证失败:{str(e)}')

    # 新增这个方法,让DRF识别为无Session认证,避免CSRF验证
    def authenticate_header(self, request):
        return 'Bearer'

四、如何使用FirebaseAuthentication类?

你不需要把它直接作为URL视图,而是把它作为认证规则应用到API视图上:

方式1:单个视图应用

在需要保护的API视图中指定认证类:

# myapp/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .authentication import FirebaseAuthentication
from rest_framework.permissions import IsAuthenticated

class VerifyFirebaseTokenView(APIView):
    authentication_classes = [FirebaseAuthentication]
    permission_classes = [IsAuthenticated]  # 要求必须认证才能访问

    def post(self, request):
        # request.user就是认证类返回的uid(或绑定的Django User)
        return Response({
            'success': True,
            'uid': request.user,
            'message': 'Firebase Token验证成功'
        })

然后在urls.py中配置这个视图:

from django.urls import path
from myapp.views import VerifyFirebaseTokenView

urlpatterns = [
    path('api/verify-firebase-token/', VerifyFirebaseTokenView.as_view(), name='verify-firebase-token'),
    # 其他业务API也可以用同样的authentication_classes配置
]

方式2:全局应用(所有API都用Firebase认证)

settings.py中配置REST Framework默认认证规则:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'myapp.authentication.FirebaseAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ]
}

五、关键疑问解答

  • 是否需要创建自定义Django视图?:是的,你需要创建类似VerifyFirebaseTokenView的视图来处理Token验证,或者直接用这个认证类保护你的业务API。
  • 何时调用FirebaseAuthentication类?:当前端请求受保护的API时,DRF会自动调用authentication_classes中的认证类,自动验证请求头里的Token。
  • CSRF验证失败怎么解决?:要么前端带上X-CSRFToken头,要么在认证类中添加authenticate_header方法(如上面代码所示),让DRF识别为无Session认证,跳过CSRF检查。

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

火山引擎 最新活动