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
相关产品推荐
相关产品推荐

