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

代用户请求需认证API端点时出现「认证凭证未提供」错误

解决「Authentication credentials were not provided.」错误的方案

核心原因

你在视图中调用login(request, user)后,Django默认会在当前请求结束时才将session数据写入数据库。而你立刻用requests发起的新请求,此时这个session还未持久化,导致后端无法识别这个sessionid,认证失败。

另外,用requests发起外部请求调用内部API本身就绕了弯路,不如直接调用业务逻辑更高效可靠。


具体解决方法

方法1:手动保存session后再发起请求

在login之后手动调用request.session.save(),确保session立即写入数据库:

def create(self, request, *args, **kwargs):
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)

    self.perform_create(serializer)
    headers = self.get_success_headers(serializer.data)

    username = serializer.validated_data['username']
    password = serializer.validated_data['password']

    user = authenticate(request, username=username, password=password)
    login(request, user)
    
    # 新增:手动保存session,确保sessionid已持久化
    request.session.save()

    session_id = request.session.session_key
    csrf_token = get_token(request)

    request_headers = {
        'X-CSRFToken': csrf_token,
        'Cookie': f"sessionid={session_id}",
    }

    url_path = reverse('send-mail-confirm-email')
    full_url = request.scheme + '://' + request.get_host() + url_path
      
    requests.get(
        full_url,
        headers=request_headers,
    )

    return Response(
            serializer.data, status=status.HTTP_201_CREATED, headers=headers
        )

方法2:直接调用内部业务逻辑(推荐)

跳过requests请求,直接调用发送邮件的核心逻辑,彻底避免跨请求的认证问题:

  1. 先把发送确认邮件的逻辑抽成独立函数(比如放在utils.py中):
# utils.py
from django.core.mail import send_mail
from django.conf import settings

def send_confirm_email(user):
    # 这里写发送确认邮件的具体逻辑
    subject = "请确认你的邮箱"
    confirm_url = f"{settings.SITE_PROTOCOL}://{settings.SITE_DOMAIN}/email-confirm/{user.pk}/"
    message = f"点击下方链接完成邮箱确认:\n{confirm_url}"
    send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, [user.email])
  1. 在视图中直接调用这个函数:
def create(self, request, *args, **kwargs):
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)

    user = serializer.save()  # perform_create内部就是调用save,直接拿到创建好的user对象
    headers = self.get_success_headers(serializer.data)

    username = serializer.validated_data['username']
    password = serializer.validated_data['password']

    user = authenticate(request, username=username, password=password)
    login(request, user)
    
    # 直接调用发送邮件逻辑,无需跨请求认证
    send_confirm_email(user)

    return Response(
            serializer.data, status=status.HTTP_201_CREATED, headers=headers
        )

方法3:检查API的认证配置

确认send-mail-confirm-email对应的视图使用的是SessionAuthentication:

from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated

class SendMailConfirmEmailView(APIView):
    authentication_classes = [SessionAuthentication]
    permission_classes = [IsAuthenticated]

    def get(self, request):
        # 视图业务逻辑
        ...

如果该API用的是TokenAuthentication,那你需要生成并传递Token,而非sessionid。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 01:47:30