【问题标题】:React Node Unable to pass cookie to the browser (crocs error)React Node 无法将 cookie 传递给浏览器(crocs 错误)
【发布时间】:2019-03-30 20:41:03
【问题描述】:

由于某种原因,我无法在浏览器中存储 cookie。

这是我第一次使用 React 和 NodeJS

我的 React 应用程序正在 localhost:3000 上运行,而 NodeJS 应用程序正在 localhost:8080 上运行

same happens to be this 的 Git 存储库

所以,我可以成功登录,将凭据存储在数据库中,并可能进行序列化和反序列化。

我没有分享 Google Strategy 以及序列化和反序列化的代码,因为我相信这个问题不存在(如果你认为你需要查看它click here

此 Google 重定向 returns at following callback

   router.get("/google/callback", passport.authenticate('google', { failureRedirect: "/", session: false }), (req, res) => {


      res.redirect("http://localhost:3000/")
  })

在我的server.js(主文件,我通过执行node server.js 启动节点服务器),我这样做是为了存储cookie

app.use(cors({
  credentials: true,
  origin: ['http://localhost:3000'] // here goes any Frontend IP Adress
}))

//We are setting cookie here 
app.use(cookieSession({
  maxAge: 24*60*60*1000, //cookies is valid for a day
  keys: ['fgfhfjhfad'] 
}))  


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

然后当我在my react frontend 中这样做时

 componentWillMount() {
         axios.get("http://localhost:8080/",  {withCredentials: true}).then(response => {
             console.log(response)
         }).catch(error => {
             console.log(error)
         })
    }

我的localhost:3000/ 看起来像这样

app.get("/", (req, res) => {
  if (req.user) {
    if (req.isFormFilled) {
      res.redirect("http://localhost:3000/home")
    } else {
      res.json(req.user)
    }
  } else {
  res.json("user does not exsist")
  }
})

它总是记录res.json("user does not exsist"),但如果我直接在浏览器中访问 localhost:3000,我可以看到我的 req.user [参见:更新下面的问题]

PS;我正在浏览器中启用跨域请求

[问题:]谁能帮我找出我可能做错了什么?

[更新:] 看来我们可能遇到了 crocs 错误,我已经更改了我的代码,我在前端收到了这个错误

在 'localhost:8080' 从源访问 XMLHttpRequest 'localhost:3000' 已被 CORS 策略阻止: 响应中的“Access-Control-Allow-Origin”标头不能是 当请求的凭据模式为“包含”时,通配符“*”。这 XMLHttpRequest 发起的请求的凭证模式是 由 withCredentials 属性控制

如果我在 axios 请求中删除 {withCredentials: true},则上述错误会消失,但随后会在 response.data 中记录 user does not exsist

【问题讨论】:

  • 虽然其他答案在技术上可能是正确的,但更基本的问题是为什么您的前端和后端在不同的端口上运行。您遇到的 CORS 错误是浏览器试图阻止网站从呼叫一个未知的,可能是恶意的外部实体。您通常希望两个服务在同一个端口上运行,以模拟它们源自同一个域。
  • @RyanVillanueva 请在此处分享您的答案stackoverflow.com/questions/52996320/using-nodejs-with-react

标签: javascript node.js reactjs passport.js


【解决方案1】:

如果您遇到 Passport-Sessions 问题,请尝试改用“express-session”。

'express-session' 自己创建 Cookie 并发送。

app.use(session({
    secret: 'keyboard cat',
    resave: false,
    saveUninitialized: true
}))

如果你使用它,你可以在每个休息呼叫中获取会话。

app.get('/', (req, res) => {
    req.session.[anyVariableUWantHere] = true;
    res.send('done');
});

现在会话已创建。

如果你在使用 React 时遇到任何问题,试试这个:

在 server.js 中: app.use(cors({ 凭据:真实, [...] }))

现在您只需要像这样在 React 中编辑“获取”:

fetch('http://localhost:3000/call', {credentials: 'include'}).then((result) => {
    return result.json()
}).then((data) => {
    //Do something
});

凭据:'include' 对于 React 获取 Session-Cookie 很重要。 默认情况下,fetch 不会加载任何 Cookie。

【讨论】:

  • 要使用 express-session,我还需要更改 app.use(passport.initialize()) 吗?
  • 我对护照了解不多……但您可能需要在这里更改一些内容。尽量确保除了快速会话之外没有其他会话
  • 非常感谢您的回答,但我正在使用护照策略,因此我可能更喜欢使用护照会话。
  • 所以您可以尝试使用凭据获取是否有帮助:包括帮助....可能足以让它工作:)
  • 你在服务器端启用了 cors 吗?
【解决方案2】:

所以通过 REST 将 Cookie 发送到:

设置 Cors 服务器端:

app.use(cors({
    'allowedHeaders': ['sessionId', 'Content-Type'],
    'exposedHeaders': ['sessionId'],
    'credentials': true,
    'origin': ['http://[FRONTEND-IP]:[FRONTEND-PORT]', 'http://[ALTERNATIVE-FRONTEND-IP]:[FRONTEND-PORT]'],
}))

对于前端,您需要像这样设置调用:

fetch('http://[API-IP]:[API-PORT]/call', {credentials: 'include'}).then((result) => {
    return result.json()
}).then((data) => {
    //Do something
});

你也可以使用异步获取:

async function loadData() {
    let response = await fetch(
        'http://[API-IP]:[APi-PORT]/call', 
        {credentials: 'include'}
    );
    return response.json();
}

当然,这适用于使用带有 json 主体的 rest 服务。 如果依赖 json 以外的其他结构,则需要手动解析响应。

另外,一篇关于 cors 的感兴趣的网络文章https://50linesofco.de/post/2017-03-06-cors-a-guided-tour

【讨论】:

  • 你是冠军,这行得通。只需将源地址更改为 3000 而不是 8080 。另外,只是为了让您知道,其他人对您的答案投了反对票,而我对此投了赞成票 :) 非常感谢 :)
  • @anny123 这对我不起作用,是因为他们有不同的端口吗?
  • @jcarlosweb Sandro 是答案的实际作者。你应该标记并问他
  • 您需要添加您用于前端的所有 IP 地址,以便根据需要允许 cors 请求。但是,您的后端运行在另一个端口上,而不是您的前端。因此,您的获取请求中需要另一个端口
  • 这让我很开心。谢谢,@Sandro Schaurer。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-24
  • 1970-01-01
  • 2019-01-20
  • 2012-02-02
  • 2018-02-27
  • 2014-06-08
  • 2015-10-31
相关资源
最近更新 更多