SO 已审核问题
我知道以下问题:
野生动物园:"被屏蔽 https://...更新到 Angular 8
如何在基本身份验证保护后面使用 Angular?
Safari 阻止 URL 请求凭据,因为它是跨源请求
但是我无法解决我的问题。
用例
我有一些CSS和JS文件不能公开公开,因此受基本身份验证保护。这些文件位于请求它们的不同来源(假设在基本身份验证保护https://mycdn.com/
下)(假设https://myapp.com/
)。
期望
当我尝试在包含这些文件的https://myapp.com
上呈现一个简单的 HTML 页面时https://mycdn.com/
我希望系统提示输入基本身份验证凭据,并让浏览器正确解析和执行它们。
结果
铬和火狐
最新的类 Chromium 和 Firefox 浏览器的行为符合我的预期,如果我的页面落后于基本身份验证,那么它们会提示我输入应用程序的站点凭据,然后它们会再次提示我输入"CDN"凭据(不是最方便的事情用户体验方面,但它可以达到目的)。之后,页面呈现没有问题。
野生动物园
另一方面,Safari(桌面[14.0.3]或移动[iOS 14])的行为有所不同。如果我的页面落后于基本身份验证,它会提示我输入凭据并开始呈现其内容,但是当引擎到达我的文件时,它不会提示我输入凭据,它会在控制台中记录一些错误消息,指出发生了401 Unauthorized
HTTP 错误,并且根据脚本,控制台还将包含一个错误,指出:
Blocked ... from asking for credentials because it is a cross-origin request.
到目前为止的分析
它可能看起来像一个混合内容(HTTPS包含在HTTPS页面中),但到目前为止我所讨论的所有内容都在HTTPS下,具有有效证书。
这似乎也是一个 CORS 问题,但实际上,服务器返回的401
实际上确实包含所有需要的 CORS 标头:
HTTP/1.1 401 Unauthorized
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
...
WWW-Authenticate: Basic realm="Fake Realm"
请注意,对script
和link
标记的文件请求GET
请求,因此允许Access-Control-Allow-Origin: *
。
测试用例
我已经测试过:
script
和link
没有crossorigin
属性的标记script
和link
具有crossorigin
属性的标记script
和link
带有crossorigin="anonymous"
标签script
和link
带有crossorigin="use-credentials"
的标签
以上所有功能在最新的Chromium和Firefox中都有效,但在macOS的Safari 14.0.3中不起作用,在iPadOS 14的Safari中不起作用,也不能在iOS 14的Safari中运行。
问题
我的问题是:有没有人在 Safari 中拥有这样的设置(经过基本身份验证的跨源资源)?你能告诉我的代码中可能导致此问题的原因吗(见下文)?
请注意,从"CDN"中删除身份验证不是一个选项。
所有这些都让我想到:
- Safari 不支持此类请求(经过基本身份验证的跨源资源)
- Safari的实现是不合规格 的
- Chromium和Firefox的实现是不合规格 的。
如何复制
我将以下示例留给您测试,它使用 HTTPBin 来模拟基本身份验证请求,该请求在 Chromium 和 Firefox 中提示输入凭据,但在 Safari 中无法提示。
用户:user
密码:passwd
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Safari basic authentication issue</title>
</head>
<body>
<!-- This emulates HTTP authentication and when correctly authenticated returns a JSON response which is invalid JS but this serves for the purpose of prompting for credentials -->
<script src="https://httpbin.org/basic-auth/user/passwd" crossorigin="use-credentials"></script>
</body>
</html>
根据 https://trac.webkit.org/changeset/228486/webkit/,问题中描述的 Safari 行为是有意为之的。具体来说,Safari 会阻止对页面子资源的跨源请求,并记录以下内容:
阻止<子资源>请求凭据,因为它是跨源请求。子资源>
https://trac.webkit.org/changeset/228486/webkit/提交消息给出了以下基本原理:
提示输入凭据以加载跨源子资源通常被导航到网页或与之交互的人员视为意外。这些子资源的跨源和隐式加载性质使得请求凭据变得可疑,因为它们不是由用户显式加载的页面的同一来源提供的,并且不保证对应于页面初始加载以外的显式用户交互。我们知道,请求凭据的子资源可能会被滥用为网络钓鱼攻击的一部分。不允许跨源子资源请求凭据似乎是合理的,因为它们的性质可疑且存在滥用风险。
2018年写的那条提交消息也提出了这样的主张:
这也将使 WebKit 的行为与 Chrome 的行为相匹配。
但是,虽然在2018年Chrome可能还阻止了子资源提示输入凭据,但对于Chrome 89来说并非如此。但是,对于Chrome 91来说,这似乎是正确的。因此,Chrome可能正在改变其行为,以执行与Safari相同的阻止。
所以我认为底线是:不可能让 Safari 提示输入子资源的凭据,并且假设提示输入子资源的凭据将继续在 Chrome 中工作(从长远来看,在 Firefox 中也是如此)。