无法从MERN应用程序的后端接收/设置浏览器中的Cookie,后端托管在heroku上,前端托管在netlify上

kknvjkwl  于 2023-05-18  发布在  其他
关注(0)|答案(2)|浏览(158)

我有一个MERN应用程序,其后端托管在Heroku上,前端托管在netlify上。部署应用程序后,我无法在浏览器中看到Cookie,但它在localhost上运行良好。我想这是由于不同的后端和前端端口,我错过了什么,请帮助

e5nqia27

e5nqia271#

你说得对。Cookie不跨域兼容。如果是的话,这将是一个严重的安全问题。解决问题的最简单方法是将cookie作为res对象发送回来,然后在前端手动设置cookie。
就拿这个来说吧。我将使用JavaScript风格的伪代码来实现这一点。不要复制粘贴这个,因为这很可能不会立即工作。这就是你要在后端做的:

// 1. Authenticate the user.
const userData = await authenticateUser();
const userToken = await verifyUser(userData);

// 2. Return the response object.
return response.status(200).json({
  status: 'success',
  data: userData,
  token: userToken,
});

在前端:

const response = await axios.post(...); // your API call, will return above object.

// set your authentication token here.
// the 'options' object will contain all possible cookie options, example would be 'secure'.
cookies.set('token', response.data.token, options);

// alternatively, set the cookie in the local storage.
localStorage.setItem('token', response.data.token);

您需要在前端相应地设置cookie。
进一步阅读:MDN Docs

编辑:您的问题不清楚。第一次你谈论的是cookie,但现在你谈论的是httpOnly cookie。请你的问题更具体些。

如果React.js是跨域的,则不可能在React.js中设置httpOnly cookie。React只对网站的“视图”负责。httpOnly cookie仅用于服务器端设置。客户端JavaScript无法读取或设置该特定cookie,但可以发送该cookie。除非您的Netlify中有可以进行服务器端操作的东西,否则我认为这是不可能的。
你最好的办法是实际上只是使用相同的域。

1cklez4t

1cklez4t2#

我也面临着同样的问题。问题是成功登录/注册后,浏览器中未设置Cookie。我需要在cookie中设置会话ID,以便在每次CRUD/RESTful API调用时检查用户身份验证。
由于没有设置cookie,我的API请求调用不包括它,用户虽然成功登录,但没有经过身份验证。因此用户无法访问需要基于会话的身份验证的页面。当然我的整个应用程序都依赖于它。
问题是,我们正在为后端和前端使用不同的域。默认情况下,出于安全原因,Chrome或其他浏览器不会为在另一个域名上托管API调用的网站(前端)设置Cookie。我不知道这些浏览器是如何停止设置cookie的,但如果我们不指定某些选项,它们肯定会这样做。
当我们为react应用程序使用http://localhost:3000,为后端使用http://localhost:7000时,这可以正常工作。但是当我们在云上部署时,问题就来了。我做了几件事来帮助我解决这个问题。我将用简单的步骤来说明,特别是在这个确切的问题部分,假设你已经正确地做了其他的事情。
以下是对我有效的步骤。看到这些箭头⬅️⬅️标记我所指的地方。
在前端React应用程序中执行(步骤1 - 2)
步骤1:在react app中的package.json文件中设置proxy。这会告诉你的React应用在任何不完整的URL(如"/update/:noteid")之前包含这个代理URL。如果URL包含类似http的内容,则代理不会设置默认代理值。

`"version": "0.1.0", 
  "private": true,
  "proxy": "https://your-backend.com", ⬅️⬅️
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.5",`

STEP2:添加"credentials" : "include" API fetch,如下所示

`fetch("your-backend-api-url",{ 
      method: "GET",
      credentials: 'include', ⬅️⬅️
      headers: { "Content-Type": "application/json" },
      ... other sptions
    });`

你可以在这里学习获取www.example.com https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#sending_a_request_with_credentials_included
在BACKEND NODE.JS应用程序中执行
STEP 3:在node.js(或后端应用程序)你需要在app.js(或你的主文件运行服务器)中install cors如果你不知道cors是什么你可以从这里学习https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
或者你可以看视频看视频:https://www.youtube.com/watch?v=CvKPeWojukc&t=410s
要做到这一点
1.使用--> npm i cors安装cors

  1. app.js-> const cors = require("cors");中需要内核
    步骤4:在应用程序中使用cors并传递一些参数,如下面的示例所示,以及代理设置,如下面的代码所示。在添加cors选项后,不要忘记添加app.set("trust proxy",1);
const app = express(); 
app.use(cors({
    origin: "https://yourfrontendurl.com", ⬅️⬅️
    credentials:  true ⬅️⬅️
}));
app.set("trust proxy",1); ⬅️⬅️

这基本上允许您的服务器接受来自特定域名的请求,该域名是您的前端网站(在本例中为https://yourfrontendurl.com)托管的域名。
步骤5:设置会话(我想你已经熟悉了),并通过cookie的设置如下

app.use(session({
    secret: process.env.sessionSecret, // your secret key to check session
    resave: false,
    saveUninitialized: false,
    cookie: { maxAge: 604800000, //one week(1000*60*60*24*7)
             sameSite: "none",
             secure : true
            }, 
    store: store
}));

我还假设你正在正确地做其他事情,比如设置mongoDB连接等。这也是我的first answer in stack overflow。请let me know如果我在某处做wrong。我会很高兴知道这一点。你也可以在下面看到我的项目页面,其中涉及到这个特定的问题解决方案。
我的package.json文件--> https://github.com/satyadalei/mynotepedia-frontend/blob/main/package.json
我的app.js文件--> https://github.com/satyadalei/mynotepedia/blob/main/app.js

相关问题