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

Posted

技术标签:

【中文标题】使用身份验证令牌的 Axios 请求有时会在 Safari 中失败【英文标题】:Axios requests using authentication token sometimes fail in Safari 【发布时间】:2020-05-18 02:22:09 【问题描述】:

我正在开发一个使用 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```

生成它的代码如下:

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

此请求在 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

但使用 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

生成它的代码如下:

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

Safari 401 响应是:

"detail": "Authentication credentials were not provided."

这是 Safari 为失败的 DELETE 请求记录的信息:

使用的 DRF api 视图基于这种混合:

class CommonViewSet(viewsets.ModelViewSet):
    authentication_classes = (TokenAuthentication, BasicAuthentication, SessionAuthentication)
    permission_classes = (IsAuthenticated,)

对于本地开发,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',
]

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

【问题讨论】:

请展示您的“simplToken”变量的示例以及如何设置它。 在 DELETE 请求 url /apis/runs/43/ 中添加斜杠(末尾有斜杠)。我认为问题在于,当您调用 /apis/runs/43 (WITHOUT SLASH) 时,safari 会正确地重定向您(使用斜杠)但在 Authorization 标头中没有身份验证令牌(标头未转发)。 chrome也做同样的事情,但它重定向授权头。 您的建议解决了问题。谢谢@mon io。 【参考方案1】:

解决方案是在引用单个对象的 url 中添加一个斜杠。 DRF Router docs 表示正确的模式是:

URL pattern: ^users/pk/$ Name: 'user-detail'

Safari 没有在重定向请求中包含身份验证令牌导致 401 错误是错误还是功能,我将留给读者。

【讨论】:

这也是我的问题。谢谢!【参考方案2】:

你看到this了吗?我不太确定,但这个讨论可能会有所帮助。

此外,由于错误与token 有关,请尝试验证其是否正确发送或添加到请求中,或者它是否具有像承载或类似的类型。

还可以尝试记录传入的请求标头及其正文,以便确保没有任何内容丢失或损坏。

由于DELETE 出现此问题,请尝试将所有请求相互比较以找出缺少的内容。

【讨论】:

感谢您的回复。我为删除添加了 Safari 的网络日志记录。将考虑添加服务器端日志记录/调试。 因此,您首先发出请求,然后被重定向,然后在没有令牌的情况下再次尝试发出请求,然后获得未经授权的响应。好吧,对于第 3 次和第 4 次请求,没有任何问题,没有带有删除请求的令牌,因此您获得了未经授权,但是为什么您在第一个请求之后被重定向,以及为什么在没有令牌的情况下再次发送请求。 尝试使用没有扩展或默认设置或其他东西的 safari,也许有什么东西让它表现得像这样 我看到但不理解 Safari 的网络日志。在删除请求 url 中添加斜线解决了这个问题——以及其他页面上的许多类似 url 问题(例如“GET /apis/runs/44/”) 这很奇怪,实际上这是我第一次看到这个,这促使我搜索更多关于实际上我没有找到太多结果的信息,但这可能会添加更多信息***.com/questions/11348479/safari-adds-trailing-slash

以上是关于使用身份验证令牌的 Axios 请求有时会在 Safari 中失败的主要内容,如果未能解决你的问题,请参考以下文章

Jmeter 身份验证令牌

找不到 Slim jwt 令牌(由 axios 请求发送)

如何在 vue 中存储、管理 REST API JWT 身份验证令牌?

在刷新身份验证令牌时处理多个未经授权的请求

Vue + Axios 处理来自服务器的所有请求错误

在javascript和axios中为来自前端的每个api调用发送firebase身份验证令牌