我在具有
"*://*/*"
权限的 Google Chrome 扩展程序中,我正在尝试从 XMLHttpRequest 切换到 Fetch API。
扩展存储用户输入的登录数据,以前直接放入 XHR 的 open() 调用中进行 HTTP Auth,但在 Fetch 下不能再直接用作参数。对于 HTTP Basic Auth,规避此限制是微不足道的,因为您可以手动设置授权标头:
fetch(url, {
headers: new Headers({ 'Authorization': 'Basic ' + btoa(login + ':' + pass) })
} });
HTTP Digest Auth 但是需要更多的交互性;您需要阅读服务器通过其 401 响应发送给您的参数,以制作有效的授权令牌。我尝试使用此代码段阅读
WWW-Authenticate
响应标头字段:
fetch(url).then(function(resp) {
resp.headers.forEach(function(val, key) { console.log(key + ' -> ' + val); });
})
但我得到的只是这个输出:
content-type -> text/html; charset=iso-8859-1
这本身是正确的,但根据 Chrome 的开发者工具,这仍然缺少大约 6 个字段。如果我使用
resp.headers.get("WWW-Authenticate")
(或与此相关的任何其他字段),我只会得到 null
.
是否有机会使用 Fetch API 访问其他字段?
当您使用 Fetch API over CORS 时,访问响应标头有限制。由于此限制,您只能访问以下标准标头:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
当您为 Google Chrome 扩展程序编写代码时,您正在使用 CORS,因此您无法访问所有标头。如果你控制服务器,你可以在响应中返回自定义信息
body
而不是headers
有关此限制的更多信息 - https://developers.google.com/web/updates/2015/03/introduction-to-fetch#response_types
Fetch 在调试时不显示标题,或者如果您
console.log(response.headers)
.
您必须使用以下方式访问标题。
fetch(url).then(resp=>{
console.log(resp.headers.get('x-auth-token'));
})
// or
fetch(url).then(resp=>{
console.log(...resp.headers);
})
你可能认为这是一个前端问题。
这是一个后端问题。
浏览器将不允许公开 Authorization 标头,除非 Backend 告诉浏览器显式公开它。
这对我有用。
在后端(API)中,将其添加到响应标头中:
response.headers.add("Access-Control-Expose-Headers","Authorization")
安全。
防止 XSS 攻击。
这个请求应该是从后端到后端。
后端将设置 httpOnly cookie 给前端。
因此,您网站上的任何第三方 JS 包都不应访问授权标头。
如果您认为让前端可以访问标头是安全的,那就去做吧。
但我建议服务器后端设置的HttpOnly Cookies 立即到您的浏览器。
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers
为了与不支持 ES2015 迭代器(并且可能还需要 fetch/Promise polyfills)的浏览器向后兼容,Headers.forEach 函数是最好的选择:
r.headers.forEach(function(value, name) {
console.log(name + ": " + value);
});
在 IE11 中使用 Bluebird 作为 Promise polyfill 和 whatwg-fetch 作为 fetch polyfill 进行了测试。 Headers.entries()、Headers.keys() 和 Headers.values() 不起作用。
为了解决这个限制问题,添加公开的标头名称就足够了。
access-control-expose-headers: headername1, headername2, ...
设置此标头后,客户端脚本能够从响应中读取这些标头(headername1,headername2,...)。
响应跨源请求,将
'Access-Control-Expose-Headers': '*'
添加到您的响应标头,以便所有标头都可以在您的客户端代码中读取。您还可以通过指定标头名称而不是通配符来指示要公开哪些标头。
请注意,根据 MDN 如果您访问的 URL 具有“凭据”,则“*”通配符将被视为文字。
如果您在 Program.cs 文件或 Startup.cs 中使用 .net,具体取决于 .net 版本,您必须执行以下操作:
builder.Services.AddCors(options =>
{
options.AddPolicy(MyAllowSpecificOrigins,
builder =>
{
builder
.SetIsOriginAllowed(p => true)
.WithOrigins("http://localhost:3000", "http://*:3000")
.AllowCredentials()
.WithExposedHeaders("X-Pagination") /*custom header*/
.AllowAnyHeader()
.AllowAnyMethod();
});
});
}
我将从上面编译我的解决方案:
对于获取标题使用:
response.headers.get('ex-token')
为了让它工作,我们必须在后端 api exposeHeader('ex-token') 上设置`
有了 Java Spring 就变成了这样:
configuration.addExposedHeader("ex-token");