403 错误 "Authentication credentials were not provided" 在 Safari 中,但在 Chrome、Edge、Firefox 等中没有 [Django + Next.js]

403 Error "Authentication credentials were not provided" in Safari, but not in Chrome, Edge, Firefox, etc. [Django + Next.js]

目前我在 Safari 和 iOS 设备中的 运行 我的页面有问题。

主要问题是 Safari 在某些端点返回 403 错误,但令牌已发送,这仅发生在此浏览器中。

例如:同时调用了以下端点,第一个在 Windows + Chrome 中,另一个在 Macbook + Safari 14 中。查询字符串, url 两个请求的令牌相同。

get_quantites enpoint with status 200

get_quantites enpoint with status 200 - headers

get_quantites enpoint with status 403

我正在使用 django-rest-framework 身份验证令牌Setup implemented here

这里有一些有用的代码:

settings.py

REST_FRAMEWORK = {
    'DEFAULT_SCHEMA_CLASS': 
    'rest_framework.schemas.coreapi.AutoSchema',
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'users.authentication.SafeJWTAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    )
}

端点

class JkmdWastagecategoriesViewSet(ModelViewSet):
queryset = JkmdWastagecategories.objects.order_by('pk')
serializer_class = JkmdWastagecategoriesSerializer

@action(detail=False)
def get_categories(self, request):
    """
    Recieve a machine name as machine_name and return
    the wastages categories
    """
    data = []
    machine_name = request.GET.get('machine_name')
  
    machine = JkmdMachine.objects.filter(name=machine_name).first()

    if machine:
        categories_pl = JkmdWastagecategories.objects.filter(
            production_line=machine.machine_group.operation.process.production_line,
        )
        serializer_pl = JkmdWastagecategoriesSerializer(
            categories_pl, many=True)
        if serializer_pl:
            data += serializer_pl.data

        categories_one = JkmdWastagecategories.objects.filter(
            operation=machine.machine_group.operation,
        )
        serializer_one = JkmdWastagecategoriesSerializer(
            categories_one, many=True)
        if serializer_one:
            data += serializer_one.data

        categories_two = JkmdWastagecategories.objects.filter(
            machine_group=machine.machine_group,
        )
        serializer_two = JkmdWastagecategoriesSerializer(
            categories_two, many=True)
        if serializer_two:
            data += serializer_two.data

        categories_three = JkmdWastagecategories.objects.filter(
            machine=machine,
        )

        serializer_three = JkmdWastagecategoriesSerializer(
            categories_three, many=True)
        if serializer_three:
            data += serializer_three.data

    return Response(data, status=status.HTTP_200_OK)

自定义 axios 对象

const service = axios.create();

service.interceptors.request.use(
  function (config) {
    let cancel;
    // Set the cancelToken object
    config.cancelToken = new axios.CancelToken(function (c) {
      cancel = c;
    });
    // Prevent repeated requests. When the previous request is not completed, the same request will not proceed
    stopRepeatRequest(
      reqList,
      config.url,
      cancel,
      `${config.url}  Request interrupted`
    );
    const token = window.localStorage.getItem("access_token");
    if (token) {
      config.headers["Authorization"] = `Token ${token}`;
    }
    config.headers["Content-Type"] = "application/json";
    return config;
  },
  function (error) {
    return Promise.reject(error);
  }
);

请求和响应目前使用 redux 进行管理。

花了一些时间寻找答案后,我终于找到了。

给了我这个想法,也许某些端点没有正确处理 DRF 的路由标准并且是正确的:

有些端点在查询字符串前没有“/”

- axios.get(`.../get_quantities?machine_name=${machine_name}`)
+ axios.get(`.../get_quantities/?machine_name=${machine_name}`)

部分端点末尾没有“/”

- axios.get('.../get_pb_list')
+ axios.get('.../get_pb_list/')