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

Django绕过Basic Auth改用Firebase Auth后request.user异常求助

问题描述

前端使用Firebase Auth,后端仅需获取id_token以绕过Django Basic Auth。但配置自定义FireBaseAuth中间件后,request.user始终为Anonymous User对象,自定义请求头丢失。调整中间件顺序无效,且不能移除AuthenticationMiddleware(需保留Django Admin功能),求解决方法。


FireBaseAuth中间件代码

class FireBaseAuth(MiddlewareMixin):

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        modified_request = self.process_request(request)
        response = self.get_response(modified_request)
        response = self.process_response(response)
        return response

    def process_request(self, request):
        middleware = "[FireBase Auth]"
        logger.info(f"{middleware} Request path: {request.path}")
        if request.path.rstrip('/').split('/')[-1] in EXCLUDE_AUTH_ENDPOINTS:
            logger.info(
                f"{middleware} Skipping auth check for: {request.path}")
            return request

        token = request.META.get("HTTP_FB_ACCESS_TOKEN")
        if not token:
            logger.info(f"{middleware} No token found")
            return HttpResponse("Unauthorized",
                                status=status.HTTP_401_UNAUTHORIZED)
        # check if token is valid
        try:
            fb_user = auth.verify_id_token(token)
            if not fb_user:
                logger.info(f"{middleware} No info found against token")
                return HttpResponse("Unauthorized",
                                    status=status.HTTP_401_UNAUTHORIZED)
            if fb_user:
                # Fetch user Data
                fb_user = auth.get_user_by_email(fb_user['email'])
                if not fb_user.email_verified:
                    logger.info(f"{middleware} User email not verified")
                    return HttpResponse("User email not verified",
                                        status=status.HTTP_401_UNAUTHORIZED)

                logger.info(
                    f"{middleware} Got user[{fb_user.email}] from firebase")

                # Check if user exists in current region
                user = User.objects.filter(email=fb_user.email).first()
                # Create user if not exists
                if not user:
                    logger.info(f"{middleware} User not Found")
                    return HttpResponse("User email not Found",status=status.HTTP_400_BAD_REQUEST)
                logger.info(f"{middleware} User Found. {user.id}")
                
                request.user = user
                setattr(request, 'user', user)
                logger.info(f"{middleware} Updated request user")
            return request

        except Exception as e:
            exec_type, exce_value, exec_traceback = sys.exc_info()
            logging.error(
                repr(traceback.format_exception(exec_type,exce_value,exec_traceback)))
            return HttpResponse(f"Unauthorized. "f"{'Token Expired' if 'expired' in str(e) else 'Invalid Token' }",status=status.HTTP_401_UNAUTHORIZED)

Settings中的Middleware配置

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'ts.middleware.AddSecurityHeadersMiddleware',
    'ts.middleware.FireBaseAuth',
]

视图代码

class GetUserAPIView(APIView):
    """
    Get user data
    """
    # authentication_classes = [JWTAuthentication]
    # permission_classes = [IsAuthenticated]

    def get(self, request):
        """
        Return data of user
        :param request: get request
        """
        api_name = " [GET: user/get_user_data] "
        try:
            # device_token = request.query_params.get('device_token', "")
            # device_type = request.query_params.get('device_type', "")
            user = request.user
............. and goes on

解决方案

1. 修复用户认证状态丢失问题

Django的AuthenticationMiddleware会校验用户的backend属性,若未设置会将用户重置为匿名用户。在中间件中设置request.user时,必须指定后端:

# 在设置request.user前添加以下代码
user.backend = 'django.contrib.auth.backends.ModelBackend'
request.user = user

2. 调整中间件顺序

  • 将CorsMiddleware移至靠前位置,确保自定义请求头能被正确传递
  • 移除重复的SecurityMiddleware
  • 保证FireBaseAuth在AuthenticationMiddleware之后执行,覆盖其设置的用户对象

调整后的MIDDLEWARE配置:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'ts.middleware.AddSecurityHeadersMiddleware',
    'ts.middleware.FireBaseAuth',
]

3. 允许自定义CORS请求头

在settings.py中添加配置,确保前端发送的自定义头能被后端接收:

CORS_ALLOW_HEADERS = [
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
    'fb-access-token',  # 新增允许自定义头
]

4. 调试建议

  • 在FireBaseAuth的process_request中打印request.META,确认HTTP_FB_ACCESS_TOKEN是否存在
  • 打印request.user在设置前后及视图中的值,追踪用户对象变化

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 10:05:58