当前位置: 首页 > 知识库问答 >
问题:

跨域会话Cookie(Netlify上Heroku React App上的Express API)

薛朝
2023-03-14

我有一个React应用程序在节点中调用API。js/Express。

前端部署在Netlify(https)中,后端部署在Heroku(https)中。

我的问题是:

  • 在开发环境(localhost)中工作的所有内容




说话很便宜,给我看代码......

  • 我使用护照(本地策略),快速会话,cors。

应用程序。js

require('./configs/passport');

// ...

const app = express();

// trust proxy (https://stackoverflow.com/questions/64958647/express-not-sending-cross-domain-cookies)
app.set("trust proxy", 1); 

app.use(
  session({
    secret: process.env.SESSION_SECRET,
    cookie: {
      sameSite: process.env.NODE_ENV === "production" ? 'none' : 'lax',
      maxAge: 60000000,
      secure: process.env.NODE_ENV === "production",
    },
    resave: true,
    saveUninitialized: false,
    ttl: 60 * 60 * 24 * 30
  })
);

app.use(passport.initialize());
app.use(passport.session());

// ...


app.use(
  cors({
    credentials: true,
    origin: [process.env.FRONTEND_APP_URL]
  })
);

//...

app.use('/api', require('./routes/auth-routes'));
app.use('/api', require('./routes/item-routes'));


CRUDendpoint(例如item routes.js):

// Create new item
router.post("/items", (req, res, next) => {
    Item.create({
        title: req.body.title,
        description: req.body.description,
        owner: req.user._id // <-- AT THIS POINT, req.user is UNDEFINED
    })
    .then(
        // ...
    );
});

  • 使用Axios时,选项“withCredentials”设置为true

用户注册和登录:

class AuthService {
  constructor() {
    let service = axios.create({
      baseURL: process.env.REACT_APP_API_URL,
      withCredentials: true
    });
    this.service = service;
  }
  
  signup = (username, password) => {
    return this.service.post('/signup', {username, password})
    .then(response => response.data)
  }

  login = (username, password) => {
    return this.service.post('/login', {username, password})
    .then(response => response.data)
  }
   
  //...
}
    axios.post(`${process.env.REACT_APP_API_URL}/items`, {
        title: this.state.title,
        description: this.state.description,
    }, {withCredentials:true})
    .then( (res) => {
        // ...
    });

共有1个答案

易奇希
2023-03-14

它并没有像预期的那样工作,因为我在Chrome Incognito上进行测试,默认情况下,Chrome会在Incognito模式下阻止第三方cookie(更多详细信息)。

下面是一个列表,其中列出了一些检查您是否存在类似问题的事项;)

如果有帮助,这里有一个清单,列出了您主要需要的不同东西;)

  • (后端)添加“信任代理”选项

如果要在Heroku上部署,请添加以下行(可以在会话设置之前添加)。

app.set("trust proxy", 1);

  • (后端)检查会话设置

特别是,选中选项sameSitesecure(此处有更多详细信息)。

以下代码将在生产中设置sameSite:'none'secure:true

app.use(
  session({
    secret: process.env.SESSION_SECRET || 'Super Secret (change it)',
    resave: true,
    saveUninitialized: false,
    cookie: {
      sameSite: process.env.NODE_ENV === "production" ? 'none' : 'lax', // must be 'none' to enable cross-site delivery
      secure: process.env.NODE_ENV === "production", // must be true if sameSite='none'
    }
  })
);
  • (后端)CORS配置
app.use(
  cors({
    credentials: true,
    origin: [process.env.FRONTEND_APP_URL]
  })
);
  • (后端)环境变量

在Heroku中设置环境变量。例如:

FRONTEND_APP_URL = https://my-project.netlify.app

重要提示:对于CORS URL,请避免在末尾使用斜杠。以下情况可能不起作用:

FRONTEND_APP_URL = https://my-project.netlify.app/ --> avoid this trailing slash!
  • (前端)发送凭据

确保您在API调用中发送凭据(您需要为所有对API的调用发送凭据,包括对用户登录的调用)。

如果您使用axios,您可以使用with凭据选项。例如:

    axios.post(`${process.env.REACT_APP_BACKEND_API_URL}/items`, {
        title: this.state.title,
        description: this.state.description,
    }, {withCredentials:true})
    .then( (res) => {
        // ...
    });
  • (浏览器)检查第三方cookie的配置

对于测试,您可能希望确保使用每个浏览器提供的默认配置。

例如,截至2021,铬阻止第三方cookie在隐姓埋名模式(但不是在“正常”模式),所以你可能想要有这样的东西:

  • 。。。并处理浏览器限制…:

最后,请记住,每个浏览器对第三方cookie都有不同的政策,总的来说,这些限制预计在未来几年会增加。

例如,预计Chrome将在2023年的某个时候阻止第三方cookie(来源)。

如果您的应用程序需要绕过这些限制,以下是一些选项:

>

实现后端

将您的后端API置于代理之下(如果您使用Netlify,您可以使用_重定向文件轻松设置代理)

 类似资料:
  • 问题内容: 我有一个小问题。 如何为多个域设置Cookie? 我确实了解安全性问题,并且我确信以前已经做过。原因是SSO。 即。 将需要将登录域设置为: domain.com,domain1.com,domain2.com。 有没有简单的方法,可以使用PHP和Cookies或其他替代方法? 问题答案: domain.com绝对没有办法为domain1.com设置cookie。您试图做的事情只能通过

  • 我目前正在从事一个托管在域上的laravel项目。此应用程序的一部分(某些功能)必须位于不同的域上。我在我的网上找到了一条路。在php中,我用以下命令映射了所有路由: 以及需要以相同方式位于另一个域上,但具有不同域的路由。好啊在主域中,我创建了一个具有src属性的图像: 指向此方法路线: 它起作用了。我在不同的域上共享同一个会话,但是,我想问你们,对于这个案例场景,你们是否知道更好的方法。我知道这

  • 问题内容: 如何使 connect.sid cookie本身仅是会话cookie,而不是持久性cookie? 我尝试失败 但是cookie仍具有到期时间戳。 问题答案: 以上工作。因此,通过将maxAge设置为null,我确实管理了expressjs以使用会话cookie。ew

  • 问题内容: 我几个月前开始使用PHP。为了为我的网站创建一个登录系统,我阅读了有关cookie和会话及其区别(cookie存储在用户的浏览器中以及服务器上的会话中)的信息。当时,我更喜欢cookie(谁不喜欢cookie ?!),只是说:“谁在乎?我在将它存储在服务器中没有任何好处”,所以,我继续使用cookie我的学士毕业项目。但是,在完成了我的应用程序的大部分工作之后,我听说对于存储用户ID的

  • 问题内容: 我不确定这是否可能。 我的“活动”网站正在处理注册并将其保存到我们的数据库中,但是我们的主站点负责处理信用卡处理。通过在主网站上处理当前的购买,会话可用于将数据传递到付款/抄送屏幕。 不必更改我的付款代码(例如接受$ _GET参数),我的变量是否应该传递过来? 例: 我的页面在上面查找地址会话变量。 问题答案: 跨域会话ID 默认情况下,使用cookie传递会话ID。由于您的网站位于不

  • 问题内容: 当我在本地发出请求时,维护FlexSession完全没有问题。但是,当我从另一台计算机发出请求时,它将为每个请求创建重复的FlexSession。我注意到每个请求的JSESSIONID是不同的,这可能是导致重复会话的原因。 但是我不知道为什么会这样。我得到的具体错误是: 我的crossdomain.xml如下: 编辑: 我们在后端使用spring-flex集成。同样,这会在多个浏览器中