CORS 的 ExpressJS 设置和 session 预检调用
ExpressJS setup for CORS and session with preflight calls
我正在尝试设置一个服务器,它正在处理第 3 方请求,即它来自我们客户的域,但我需要通过此 Express 应用程序将请求代理到我们的 API。我需要在 session 中存储一些信息,为此我使用 Redis 缓存来存储实际数据。
我在尝试执行此操作时遇到了一系列 CORS 问题 运行。到目前为止,这是我得到的配置。它可以在我的本地开发机器上找到,在不同的端口上模拟两个服务器,但是当我部署时,我在 Preflight OPTION 上收到 CORS No Allow Credentials
错误,在随后的 POST 上收到 NS_ERROR_DOM_BAD_URI
。
我在解决这个问题时基本上遇到了困难。我以为是起源,但我已经定义了一个起源白名单,但没有帮助。
如果对我的配置有任何帮助,我们将不胜感激
// set session cookie options, all environments
const cookieOptions = {
maxAge: 24 * 60 * 60 * 1000, // 24 hours
httpOnly: true,
sameSite: 'none', // sameSite and secure are necessary
secure: true // to set 3rd party cookie for session
}
// express session configuration options
const sessionOptions = {
store: new RedisStore({ client: redisClient }),
secret: process.env.sessionKey,
cookie: cookieOptions,
resave: false,
saveUninitialized: true,
}
app.set('trust proxy', 2)
app.use( cors({
origin: validateCorsOrigins, // also had the same error with this set to true
methods: 'GET, PUT, PATCH, POST, DELETE, HEAD, OPTIONS', // OPTIONS is necessary for preflight
credentials: true // client will have to set credentials as well
})
)
app.use( session( sessionOptions ) )
// POST endpoint
app.post('/api/cars', (req, res, next) => {
const session = req.session
....do some processing....
session.vin = vin
res.json({ cars: cars })
})
我必须使用 trust proxy
设置,因为我要部署到 Docker 容器中。
客户代码
var headers = new Headers({ 'Content-Type': 'application/json', 'Accept': 'application/json' });
var payload = { <payload body here/> };
var request = new Request(url, {
method: 'POST',
body: JSON.stringify(payload),
mode: 'cors',
credentials: 'include',
headers: headers
});
const response = await fetch(request);
const json = await response.json().catch(function (error) {
console.log(error);
});
...
预检请求Headers 选项调用
OPTIONS /api/cars HTTP/2
Host: proxyhost.example.com
User-Agent: Mozilla/5.0
Firefox/90.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Referer: https://localhost:5000/
Origin: https://localhost:5000
DNT: 1
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
Cache-Control: max-age=0
预检响应Headers
HTTP/2 200 OK
server: Kestrel
access-control-allow-headers: content-type
access-control-allow-origin: *
date: Sun, 20 Jun 2021 17:05:27 GMT
content-length: 0
X-Firefox-Spdy: h2
POST
Referrer Policy strict-origin-when-cross-origin
POST 请求 Headers
POST /api/cars undefined
Host: proxyhost.example.com
User-Agent: Mozilla/5.0
Firefox/90.0
Accept: application/json
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://localhost:5000/
content-type: application/json
Origin: https://localhost:5000
Content-Length: 44
DNT: 1
Connection: keep-alive
Cookie: <cookie stuff/>
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
这个问题的答案原来是 Azure AppServices 覆盖我的应用程序的 CORS 设置的问题。如果定义了 AppServices CORS 设置,则它们将优先。您必须在 AppService 上禁用 CORS 才能使节点应用程序上的 CORS 设置生效。
$ az webapp cors remove --allowed-origins --resource-group "<resource_group_name>" --name "<app_service_name>" --slot "<slot_name>"
结果应该是:
{
"allowedOrigins": [],
"supportCredentials": false
}
我正在尝试设置一个服务器,它正在处理第 3 方请求,即它来自我们客户的域,但我需要通过此 Express 应用程序将请求代理到我们的 API。我需要在 session 中存储一些信息,为此我使用 Redis 缓存来存储实际数据。
我在尝试执行此操作时遇到了一系列 CORS 问题 运行。到目前为止,这是我得到的配置。它可以在我的本地开发机器上找到,在不同的端口上模拟两个服务器,但是当我部署时,我在 Preflight OPTION 上收到 CORS No Allow Credentials
错误,在随后的 POST 上收到 NS_ERROR_DOM_BAD_URI
。
我在解决这个问题时基本上遇到了困难。我以为是起源,但我已经定义了一个起源白名单,但没有帮助。
如果对我的配置有任何帮助,我们将不胜感激
// set session cookie options, all environments
const cookieOptions = {
maxAge: 24 * 60 * 60 * 1000, // 24 hours
httpOnly: true,
sameSite: 'none', // sameSite and secure are necessary
secure: true // to set 3rd party cookie for session
}
// express session configuration options
const sessionOptions = {
store: new RedisStore({ client: redisClient }),
secret: process.env.sessionKey,
cookie: cookieOptions,
resave: false,
saveUninitialized: true,
}
app.set('trust proxy', 2)
app.use( cors({
origin: validateCorsOrigins, // also had the same error with this set to true
methods: 'GET, PUT, PATCH, POST, DELETE, HEAD, OPTIONS', // OPTIONS is necessary for preflight
credentials: true // client will have to set credentials as well
})
)
app.use( session( sessionOptions ) )
// POST endpoint
app.post('/api/cars', (req, res, next) => {
const session = req.session
....do some processing....
session.vin = vin
res.json({ cars: cars })
})
我必须使用 trust proxy
设置,因为我要部署到 Docker 容器中。
客户代码
var headers = new Headers({ 'Content-Type': 'application/json', 'Accept': 'application/json' });
var payload = { <payload body here/> };
var request = new Request(url, {
method: 'POST',
body: JSON.stringify(payload),
mode: 'cors',
credentials: 'include',
headers: headers
});
const response = await fetch(request);
const json = await response.json().catch(function (error) {
console.log(error);
});
...
预检请求Headers 选项调用
OPTIONS /api/cars HTTP/2
Host: proxyhost.example.com
User-Agent: Mozilla/5.0
Firefox/90.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Referer: https://localhost:5000/
Origin: https://localhost:5000
DNT: 1
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
Cache-Control: max-age=0
预检响应Headers
HTTP/2 200 OK
server: Kestrel
access-control-allow-headers: content-type
access-control-allow-origin: *
date: Sun, 20 Jun 2021 17:05:27 GMT
content-length: 0
X-Firefox-Spdy: h2
POST
Referrer Policy strict-origin-when-cross-origin
POST 请求 Headers
POST /api/cars undefined
Host: proxyhost.example.com
User-Agent: Mozilla/5.0
Firefox/90.0
Accept: application/json
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://localhost:5000/
content-type: application/json
Origin: https://localhost:5000
Content-Length: 44
DNT: 1
Connection: keep-alive
Cookie: <cookie stuff/>
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
这个问题的答案原来是 Azure AppServices 覆盖我的应用程序的 CORS 设置的问题。如果定义了 AppServices CORS 设置,则它们将优先。您必须在 AppService 上禁用 CORS 才能使节点应用程序上的 CORS 设置生效。
$ az webapp cors remove --allowed-origins --resource-group "<resource_group_name>" --name "<app_service_name>" --slot "<slot_name>"
结果应该是:
{
"allowedOrigins": [],
"supportCredentials": false
}