我正在尝试新的 Fetch API,但在使用 Cookie 时遇到问题。具体来说,登录成功后,以后的请求中会有一个 Cookie 标头,但 Fetch 似乎会忽略该标头,并且我使用 Fetch 发出的所有请求都是未经授权的。
是因为 Fetch 还没有准备好,还是 Fetch 不能与 Cookie 配合使用?
我使用 Webpack 构建我的应用程序。我也在React Native中使用Fetch,没有同样的问题。
Fetch默认不使用cookie。要启用 cookie,请执行此操作:
fetch(url, {
credentials: "same-origin"
}).then(...).catch(...);
除了@Khanetor的回答之外,对于那些处理跨源请求的人:
credentials: 'include'
示例 JSON 获取请求:
fetch(url, {
method: 'GET',
credentials: 'include'
})
.then((response) => response.json())
.then((json) => {
console.log('Gotcha');
}).catch((err) => {
console.log(err);
});
https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials
刚刚解决了。就两个f。暴力的日子
对我来说,秘诀如下:
我调用 POST /api/auth 看到 cookie 已成功接收。
然后使用
credentials: 'include'
调用 GET /api/users/ 并得到 401 unauth,因为没有随请求发送 cookie。关键是为第一个
credentials: 'include'
呼叫设置/api/auth
。
如果您在 2019 年阅读本文,则
credentials: "same-origin"
是默认值。
fetch(url).then
以编程方式覆盖浏览器端的
Cookie
标头不起作用。
在
fetch
文档中,提到了 注意某些名称是被禁止的。。而 Cookie
恰好是禁止的标头名称之一,无法以编程方式修改。以下面的代码为例:
Cookie: 'xxx=yyy'
将被忽略,如果有的话,浏览器将始终将document.cookie
的值作为cookie发送。fetch('https://httpbin.org/cookies', {
headers: {
Cookie: 'xxx=yyy'
}
}).then(response => response.json())
.then(data => console.log(JSON.stringify(data, null, 2)));
附注您可以通过在 Chrome 浏览器中打开
https://httpbin.org/cookies/set/foo/bar来创建示例 cookie
foo=bar
。
有关详细信息,请参阅禁止的标头名称。
只是为
.net
webapi2
用户添加正确答案。
如果您使用
cors
,因为您的客户端站点与您的 webapi
的地址不同,那么您还需要在服务器端配置中包含 SupportsCredentials=true
。
// Access-Control-Allow-Origin
// https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api
var cors = new EnableCorsAttribute(Settings.CORSSites,"*", "*");
cors.SupportsCredentials = true;
config.EnableCors(cors);
这对我有用:
import Cookies from 'universal-cookie';
const cookies = new Cookies();
function headers(set_cookie=false) {
let headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
};
if (set_cookie) {
headers['Authorization'] = "Bearer " + cookies.get('remember_user_token');
}
return headers;
}
然后建立您的通话:
export function fetchTests(user_id) {
return function (dispatch) {
let data = {
method: 'POST',
credentials: 'same-origin',
mode: 'same-origin',
body: JSON.stringify({
user_id: user_id
}),
headers: headers(true)
};
return fetch('/api/v1/tests/listing/', data)
.then(response => response.json())
.then(json => dispatch(receiveTests(json)));
};
}
我也正在使用:
credentials: "same-origin"
它曾经可以工作,然后突然不再工作了,经过深入研究,我意识到我已将网站网址更改为
http://192.168.1.100
以在局域网中测试它,这就是用于发送请求的网址,即使我在 http://localhost:3000
。
所以总而言之,请确保页面的域与获取网址的域匹配。
我的问题是我的 cookie 设置在特定的 URL 路径上(例如,
/auth
),但我fetch
到了不同的路径。我需要将 cookie 的 path
设置为 /
。
如果
fetch
没有发送凭据,即使该请求并非旨在进行跨源调用,这可能是因为由于请求源和源之间的协议差异,该请求被作为跨源处理。响应的位置。
我观察到我的服务器正在返回带有
Location
URL 的 http
标头,而连接是通过 https
建立的。因此,浏览器将请求视为跨域并应用跨域规则。值得注意的是,Firefox(版本 114.0.2)和 Safari(版本 16.1)在这种情况下没有显示任何警告,但 Chrome(版本 114.0.5735.198)显示了 (blocked:mixed-content)
错误,这有助于识别问题。
如果有人感兴趣,在这种特殊情况下,SSL 终止是在反向代理中执行的,但是由于配置错误,
gunicorn
服务器无法正确处理它,特别是与 secure-scheme-headers
和 forwarded_allow_ips
设置相关。在服务器端解决这些设置后,fetch
开始在所有浏览器中正常工作。
我浪费了三个小时寻找解决方案,所以我决定分享我的发现。
login(email: string, password: string): Promise<User | null> {
return fetch('http://localhost:8080/api/login', {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: email,
password: password,
}),
})
.then(response => {
this.handleError(response);
return response.ok ? response.json() : null;
})
}
Set-Cookies
header 的请求中设置,而不仅仅是我们期望携带 cookie 的后续请求;Access-Control-Allow-Headers
必须列出客户端可以发送的所有可能的标头。与您的预期相反,通配符星号值不起作用。如果客户端发送至少一个未知标头,它也会破坏 cors。