使用express和passport时未设置Cookie

5

我花了很长时间试图弄清楚为什么它不能工作。

我正在使用React实现登录页面。这个页面使用axios将用户和密码发送到后端(nodejs + express):

const login = useCallback(e => {
    e.preventDefault()
    fetch(process.env.REACT_APP_HOST + '/login', {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        username: e.target.elements.username.value,
        password: e.target.elements.password.value
      })
    })
      .then(response => {
        if (response.ok) {
          return response.json()
        } else if (response.status === 401) {
          throw new Error('Invalid user or pass.')
        } else {
          throw new Error('An error ocurred')
        }
       ...
      })

  }, [])

在后端,我有一个路由来接收这些数据并在LDAP系统上检查。因此,我使用JWT生成令牌并将其保存在令牌中。

const express = require('express'),
    passport = require('passport'),
    bodyParser = require('body-parser'),
    jwt = require('jsonwebtoken'),
    cors = require('cors')
    cookieParser = require('cookie-parser')
    LdapStrategy = require('passport-ldapauth');

let app = express();
app.use(cookieParser())
app.use(cors());

....

app.post('/login', function (req, res, next) {

        passport.authenticate('ldapauth', { session: false }, function (err, user, info) {

            const token = jwt.sign(user, env.authSecret)
            res.cookie('cookie_token', token) //it doesn't set the cookie

            if (err) {
                return next(err)
            }
            if (!user) {
                res.sendStatus(401)
            } else {
                return res.status(200).send({ firstName: user.givenName});
            }
        })(req, res, next);
    });

问题在于令牌为空,没有被设置。

1
你在Postman或类似的工具中验证过cookie头是否未被设置吗? - David S.
我现在检查一下,在Postman上它已经被设置了。 - mr.abdo
1
请在浏览器中检查,可能是cookie的域问题。 - David S.
1个回答

4

有几件事情。在你的react fetch post方法中,你需要在httpheader旁边添加

withCredentials: true,

 fetch(process.env.REACT_APP_HOST + '/login', {
  method: 'POST',
  withCredentials: true,
  credentials: 'include',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    username: e.target.elements.username.value,
    password: e.target.elements.password.value
  })
})

在您的Node.js部分中,您正在使用cors但验证所有来源。这不会与凭据一起使用。您需要像这样使用cors来验证特定来源并将凭据设置为true-
app.use(cors({credentials: true, origin: 'http://localhost:4200'}));

之后,您可以通过发送cookie来完成

res.cookie('cookie_token', token, { maxAge: 900000 }) 

chrom application cookie view

这样,cookie将会被发送到客户端,一旦cookie到达客户端,您可以使用document.cookie或像"js-cookie"这样的其他程序包检索cookie。


哪一部分出了问题?因为我已经在Angular和Node.js中使用Chrome测试过这段代码,它是可以工作的。你能在Chrome开发者控制台中看到cookie吗? - Asif Rahman
2
我解决了,我按照你的建议做了,并且只改变了这段代码:credentials: 'include', - mr.abdo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接