使用 ngrok 隧道时难以设置 Cookie(Node.js 上的 Express 服务器、React 应用程序前端)

Dav*_*idH 6 cookies node.js express reactjs ngrok

正如标题中所述,在使用 ngrok 进行隧道传输时,我很难设置用于身份验证目的的 http cookie。

\n

当我在开发环境中运行从 localhost 到 localhost 端点的查询时,以下代码工作正常(显然指定了相关端点),但一旦我开始查询 ngrok 隧道端点,它就会崩溃。

\n

前端 api 查询(简化为大型应用程序的一部分)

\n
function fetchRequest (path, options) {\n  const endpoint = 'http://xxx.ngrok.io'; // the ngrok tunnel endpoint\n  return fetch(endpoint + path, options)\n    .then(res => {\n      return res.json();\n    })\n    .catch((err) => {\n      console.log('Error:', err);\n    });\n}\n\nfunction postRequest (url, body, credentials='include') {\n  return fetchRequest(`${url}`, {\n    method: 'POST',\n    withCredentials: true,\n    credentials: credentials,\n    headers: {'Content-Type': 'application/json', Accept: 'application.json'},\n    body: JSON.stringify(body)\n  });\n}\n\n// data to be passed to backend for authentication\nlet data = {pin: pin, username : username};\n\npostRequest('/',data)\n\n
Run Code Online (Sandbox Code Playgroud)\n

Node.js 上的 Express 服务器,带有 ngrok 隧道 (app.js)

\n
const express = require('express')\nconst session = require('express-session')\nconst cors = require('cors')\nconst router = require('./router');\nconst tunnel = require('./ngrok')\n\nconst app = express()\nconst port = process.env.PORT || 4001;\n\napp.use(cors({\n  origin: 'http://localhost:3000'\n  credentials: true,\n}))\napp.use(express.json());\n\nconst expiryDate = new Date(Date.now() + 60 * 60 * 1000) // 1 hour\napp.use(session({\n  secret: 'keyboard cat',\n  resave: false,\n  saveUninitialized: true,\n  cookie: {\n    httpOnly: true,\n    expires: expiryDate\n    // sameSite: 'none'\n    // secure: true \n  }\n}))\napp.use(router)\n\nlet useNGROK = true;\n\nif (useNGROK) {\n  app.listen(port, () => {\n    console.log(`Example app listening at http://localhost:${port}`)\n  })\n  tunnel.createHTTPtunnel().then((url) => {\n    console.log(`New tunnel created with endpoint: ${url}`)\n  });\n} else {\n  app.listen(port, () => {\n    console.log(`Example app listening at http://localhost:${port}`)\n  })\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n

Ngrok 配置 (ngrok.js)

\n
const ngrok = require('ngrok');\nconst find = require('find-process');\nconst port = process.env.PORT || '3000';\n\nconst tunnel = {\n  createHTTPtunnel: async function () {\n\n    const list = await find('name', 'ngrok');\n\n    if (list.length > 0) {\n      let api = ngrok.getApi();\n      if (api == null) {\n        this.kill_existing_tunnel();\n      } else {\n        let open_tunnels = await ngrok.getApi().listTunnels();\n        return open_tunnels.tunnels[0].public_url;\n      }\n    }\n\n    let ngrok_config = {\n        proto: 'http',\n        bind_tls: false,\n        name: process.env.NGROK_NAME,\n        hostname: process.env.NGROK_CUSTOM_DOMAIN,\n        // host_header: 'rewrite',\n        authtoken: '',\n        region: 'eu',\n    };\n\n    return ngrok.connect({ ...ngrok_config, addr: port });\n  },\n\n  kill_existing_tunnel: async () => {\n    const list = await find('name', 'ngrok');\n    list.forEach((p) => {\n      try {\n        process.kill(p.pid);\n        console.log(`Killed process: ${p.name} before creating ngrok tunnel`);\n      } catch (e) {\n        console.log(e);\n      }\n    });\n  }\n  \n}\n\nmodule.exports = tunnel;\n\n
Run Code Online (Sandbox Code Playgroud)\n

** 路由器和控制器(分别为 router.js 和controller.js) **

\n
*router.js*\nconst router = require('express').Router();\nconst example = require('./controller')\n\nrouter.post('/', example.authenticate);\n\nmodule.exports = router;\n\n*controller.js*\nasync function authenticate (req, res) {\n  try {\n    res.send(JSON.stringify('trying to send cookie'))\n  } catch (e) {\n    console.log('Error', e)\n    res.sendStatus(500)\n  }\n}\n\nmodule.exports = {\n  authenticate\n};\n\n\n
Run Code Online (Sandbox Code Playgroud)\n

检查网络请求中的 Set-Cookie 响应标头时,会提供以下信息:

\n

此 Set-Cookie 标头未指定 \xe2\x80\x99t 指定 \xe2\x80\x9cSameSite\xe2\x80\x9d 属性,并默认为 \xe2\x80\x9cSameSite=Lax\xe2\x80\x9d 并被阻止,因为它来自跨站点响应,而不是对顶级导航的响应。必须使用 \xe2\x80\x9cSameSite=None\xe2\x80\x9d 设置 Set-Cookie 才能启用跨站点使用。

\n

尝试修复 1//\n如果我将以下选项添加到 cookie {sameSite: \xe2\x80\x98none\xe2\x80\x99, secure:true},请修改 ngrok 配置以设置 {bind_tls: true} 并运行 https在我的前端(根据创建反应应用程序文档使用自定义 SSL 证书),并查询 https 隧道,然后在来自服务器的响应中根本没有收到 cookie(发送请求并收到响应 200,但没有曲奇饼)。

\n

尝试修复 2//\n我还尝试更改host_header选项以在 ngrok 配置中重写(以镜像来自 localhost 而不是来自 ngrok 的响应),但这不起作用。

\n

任何帮助将不胜感激,因为我经验不足,而且我陷入困境!

\n