使用身份验证令牌的 Axios 请求有时会在 Safari 中失败

sof*_*ave 6 safari django-rest-framework django-rest-auth axios

我正在开发一个使用 axios (0.19.0) 的 React (16.9.0) 单页应用程序。axios 请求使用令牌身份验证来访问运行 django-rest-framework (3.6.4) 和 django-cors-headers (3.1.1) 的服务器。身份验证令牌是在登录期间由 django-rest-auth (0.9.5) 生成的。

该应用程序在 Chrome 和 Firefox 中可靠运行。在 Safari 中,某些请求会因 401 错误而失败。

此请求在所有三个浏览器中均成功:

INFO basehttp: "GET /apis/games/?slug=pop HTTP/1.1" 200 60932```
Run Code Online (Sandbox Code Playgroud)

生成它的代码如下所示:

    axios
      .get(`${simplUrl}/apis/games/?slug=${gameSlug}`, {
        headers: { Authorization: simplToken },
      })
      .then(res => {
        this.setState({
          game: res.data[0],
        });
      ...
Run Code Online (Sandbox Code Playgroud)

此请求在 Safari 中失败:

INFO basehttp: "OPTIONS /apis/runs/43 HTTP/1.1" 200 0
INFO basehttp: "DELETE /apis/runs/43 HTTP/1.1" 301 0
INFO basehttp: "OPTIONS /apis/runs/43/ HTTP/1.1" 200 0
WARNING basehttp: "DELETE /apis/runs/43/ HTTP/1.1" 401 58
Run Code Online (Sandbox Code Playgroud)

但使用 Chrome 成功了:

INFO basehttp: "OPTIONS /apis/runs/43 HTTP/1.1" 200 0
INFO basehttp: "DELETE /apis/runs/43 HTTP/1.1" 301 0
INFO basehttp: "OPTIONS /apis/runs/43/ HTTP/1.1" 200 0
INFO basehttp: "DELETE /apis/runs/43/ HTTP/1.1" 204 0
Run Code Online (Sandbox Code Playgroud)

生成它的代码如下所示:

      const url = `${simplUrl}/apis/runs/${run.id}`;
      // console.log('url:', url);
      axios
        .delete(url, {
          headers: { Authorization: simplToken },
        })
        .then(res => {
          // console.log(res);
          afterDelete();
        });
Run Code Online (Sandbox Code Playgroud)

Safari 401 响应是:

"detail": "Authentication credentials were not provided."
Run Code Online (Sandbox Code Playgroud)

这是 Safari 为失败的 DELETE 请求记录的信息: 在此输入图像描述

DRF api 视图的使用基于以下混合:

class CommonViewSet(viewsets.ModelViewSet):
    authentication_classes = (TokenAuthentication, BasicAuthentication, SessionAuthentication)
    permission_classes = (IsAuthenticated,)
Run Code Online (Sandbox Code Playgroud)

对于本地开发,DRF服务器的CORS设置为:

CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_HEADERS = [
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
]
Run Code Online (Sandbox Code Playgroud)

我不明白为什么有些请求在 Safari 中失败,而另一些则不然。大多数情况下,我想确保所有请求在所有三个浏览器中都能正常工作。

sof*_*ave 6

解决方案是在引用单个对象的 url 中添加尾部斜杠。DRF Router 文档表明正确的模式是:

URL pattern: ^users/{pk}/$ Name: 'user-detail'
Run Code Online (Sandbox Code Playgroud)

无论是 bug 还是 Safari 未在重定向请求中包含身份验证令牌而导致 401 错误的功能,我都会留给读者。