Express + Passport session 适用于 Postman 但不适用于浏览器

Express + Passport session works in Postman but not in browser

我在 http://localhost:9000

上有一个节点 js 服务器 运行

和一个在 http://localhost:3000

上使用 React js 运行 的客户端

我可以通过在端点 http:localhost:9000/api/v1/authenticate 中发出 post 请求来验证用户身份,并向客户端发送一个 cookie,正如您在我的 response header

上看到的那样
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:3000
Connection: keep-alive
Content-Length: 51
Content-Security-Policy: default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests
Content-Type: application/json; charset=utf-8
Date: Fri, 25 Dec 2020 14:03:48 GMT
ETag: W/"33-tyk8lJX6mfHZ8N08Hj//Q3TUtmY"
Expect-CT: max-age=0
Referrer-Policy: no-referrer
Set-Cookie: connect.sid=s%3ALVe2uJLDGv502_M70nCSfjfawWhXG0Zx.zDCxMUAJE54wKO0ecJogSPLWZIQoOdHqF387XEX1A7E; Path=/; Expires=Fri, 08 Jan 2021 14:03:48 GMT; HttpOnly
Strict-Transport-Security: max-age=15552000; includeSubDomains
Vary: Origin
X-Content-Type-Options: nosniff
X-DNS-Prefetch-Control: off
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-Permitted-Cross-Domain-Policies: none
X-XSS-Protection: 0

现在,在我登录并检查用户是否通过身份验证后 /check-session, 我能够在 POSTMAN 中获取数据并且 req.session.passport 数据存在。

但是当我在前端使用 axios

发出请求时,我无法获得相同的结果
export const checkAuthSession = async () => {
    try {
        const req = await axios({
            method: 'GET',
            url: '/check-session',
            withCredentials: true,
        });

        return Promise.resolve(req.data);
    } catch (e) {
        return Promise.reject(e);
    }
}

我希望在前端登录后获得 200 状态并获取数据,但我得到 404。

这些是我用axios发出请求后的requestresponse header:

请求Header

Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Cookie: connect.sid=s%3Ag7erGfrj2XWv5jrFXrSk4kJH-qvuCCa7.8e2cnCs1dduo86Ydne1sPDRSoAlYwdiAbGcZJqluZgc
Host: localhost:9000
Origin: http://localhost:3000
Referer: http://localhost:3000/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66

回复Header

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:3000
Connection: keep-alive
Content-Length: 9
Content-Security-Policy: default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests
Content-Type: text/plain; charset=utf-8
Date: Fri, 25 Dec 2020 14:17:18 GMT
ETag: W/"9-0gXL1ngzMqISxa6S1zx3F4wtLyg"
Expect-CT: max-age=0
Referrer-Policy: no-referrer
Strict-Transport-Security: max-age=15552000; includeSubDomains
Vary: Origin
X-Content-Type-Options: nosniff
X-DNS-Prefetch-Control: off
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-Permitted-Cross-Domain-Policies: none
X-XSS-Protection: 0

这就是我在 express 中配置 CORS 的方式:

app.use(cors({
  origin: 'http://localhost:3000',
  credentials: true
}));

终于找到答案了:

在我的 axios 请求中,我只在 /check-session 端点设置了 withCredentials: true 选项。

要修复它,我必须为所有请求设置凭据。

axios.defaults.withCredentials = true;

正如 MDN 所说:

For a CORS request with credentials, in order for browsers to expose the response to frontend JavaScript code, both the server (using the Access-Control-Allow-Credentials header) and the client (by setting the credentials mode for the XHR, Fetch, or Ajax request) must indicate that they’re opting in to including credentials.