NodeJS res.cookie未在浏览器中设置cookie

9fkzdhlc  于 2022-11-29  发布在  Node.js
关注(0)|答案(4)|浏览(172)

我目前正在尝试设置一个Node/Express应用程序,让React客户端与之交互。我设置passport来处理与JWT的身份验证。当用户登录时,我验证电子邮件/密码。然后我设置cookie:

res.cookie('jwt', token, { httpOnly: true, secure: false });

我看到令牌在响应头中被传回,但当我在Developer Tools〉Application〉Cookies下检查Chrome浏览器的cookie时,我看到的是一个空cookie。我做错了什么,我该如何在后续请求中发送响应头中的jwt?

服务器/应用程序.js

const app = express()

app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());

app.use(cookieParser());

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

app.post('/login', (req, res) => {
  passport.authenticate('local', { session: false }, (error, user) => {
    if (error || !user) {
      res.status(400).json({ error });
    }

    // Construct JWT payload
    const payload = {
      email: user.email,
      expires: Date.now() + parseInt(process.env.JWT_EXPIRATION_MS),
    };

    // Assign payload to req.user
    req.login(payload, {session: false}, (error) => {
      if (error) {
        res.status(400).send({ error });
      }
      // Generate a signed JWT
      const token = jwt.sign(JSON.stringify(payload), process.env.JWT_SECRET);

      // Assign JWT to cookie
      res.cookie('jwt', token, { httpOnly: true, secure: false });
      res.status(200).send({ email: user.email });
    });
  })(req, res);
});

客户端/登录模式.js

handleLogin = async () => {
    const { name, email, password } = this.state

    try{
      const res = await axios.post('http://localhost:8080/login', {
        email: email,
        password: password,
      })

      if(res.status == 200){
        console.log("Logged in")
        console.log(res)
      }

    } catch (err) {
      console.log(err)
    }
  }

编辑:我目前的解决方案是将令牌作为有效负载的一部分发送。然后我的react客户端从有效负载中获取令牌并将其存储在浏览器的cookie中。有没有办法避免这种解决方案(参见下面的示例)?
伺服器

res.status(200).send({ email: user.email, jwt: token });

委托人

if(res.status == 200){
    cookies.set('jwt', res.data.jwt)
    cookies.set('email', res.data.email)
  }
ryoqjall

ryoqjall1#

您已经设置了启用httpOnly标志的cookie。大多数现代浏览器通过开发者工具限制对此类cookie的读取访问。您可以在这里阅读更多有关它的信息。
如果希望在开发环境中查看Cookie的内容,请将httpOnly设置为false。

mzsu5hc0

mzsu5hc02#

我发现这个解决方案既适用于本地开发也适用于生产(而且还支持局域网访问,例如,当您通过局域网IP地址(如http://192.168.xxx.xxx:<port>)访问网站时):

// Set CORS options 
const cors = require(`cors`)

const whitelist = [ 
    'http://localhost:<application port>', // not https
    'https://yourprod.ip.address.com' // must be https!
    'http://<your local IP>:<port>', // optional, LAN access
    // ...
]

const corsOptions = {
    credentials: true,
    origin: (origin, callback) => {

        // `!origin` allows server-to-server requests (ie, localhost requests)
        if(!origin || whitelist.indexOf(origin) !== -1) {
            callback(null, true)
        } else {
            callback(new Error("Not allowed by CORS: "+ origin))
        }
    },
    optionsSuccessStatus: 200
}

app.use(cors(corsOptions))

然后在身份验证端点上:

// Set Cookie
const cookieContent = 'this is a cookie'

const cookieOptions = {
  httpOnly: true,    // safety, does not allow cookie to be read in the frontend javascript
  maxAge: 24*3600*1, // cookie age in seconds
  sameSite: 'Strict' // works for local development
}

if(process.env.NODE_ENV === 'production') {

  // these options work on a https server
  cookieOptions.secure = true 
  cookieOptions.sameSite= 'None'
}

res.cookie(
  'cookie-tag', 
  refreshToken, 
  cookieOptions
)
res.json(cookieContent)
h43kikqp

h43kikqp3#

对我有效的方法是在cors包中设置app.use(cors({ origin: true, credentials: true }))。在从后端获取时也设置withCredentials: true, credentials: 'include'

nwo49xxi

nwo49xxi4#

在调用axis.post()时,必须传递{withCredentials: true, credentials: 'include'}作为第二个参数,只有这样浏览器才能设置cookie。

相关问题