首页 > 解决方案 > 如何使用后端 Node.js Express-Sessions 对 React 前端进行身份验证?

问题描述

我不再使用 firestore auth 来了解如何制作自己的身份验证系统。

我的目标:

  1. 创建一个允许用户注册和登录的 React Web 应用程序。
  2. 经过身份验证的用户可以在 restAPI 上进行操作,这是连接到 Postgres 的 NodeJS。

我看了很多教程。他们中的大多数人都将快速会话作为解决方案。但是,当我尝试它时 - 这些会话 cookie 仅在我的浏览器在 express uri 上时提供。

问题是......在前端,当我通过 fetch 将 CRUD 操作发送到我的 express api 时,我的 react-app 没有得到那个 cookie。

是我正在做的传统方式来处理后端服务器的身份验证吗?我怎样才能解决这个问题?

表示:


require("dotenv").config();
const express = require("express");
const db = require("./db");
var session = require("express-session");
var pgSession = require("connect-pg-simple")(session);

const app = express(); //create an instance;
// :id url param.
app.use(
    session({
      store: new pgSession({ pool: db.pool }),
      secret: "secret",
      resave: false,
      saveUninitialized: false,
      cookie: { maxAge: 303 * 24 * 60 * 60 * 1000 }, //30days
    })
  );

app.use(function (req, res, next) {
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader(
    "Access-Control-Allow-Methods",
    "GET, POST, OPTIONS, PUT, PATCH, DELETE"
  );
  res.setHeader(
    "Access-Control-Allow-Headers",
    "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers,X-Access-Token,XKey,Authorization"
  );
  next();
});

app.use(express.json());

app.post("/addUser", async (req, res) => {
  try {
    const results = await db.query(
      "INSERT INTO USERS (email, password) values ($1, $2) returning *",
      [req.body.email, req.body.password]
    );
    console.log(results);
    req.session.isAuth = true;
    res.status(201).json({
      status: "success",
      data: {
        user: results.rows,
      },
    });

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

反应JS


import React, { useEffect, useState } from "react";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link,
  Redirect,
} from "react-router-dom";
const App = () => {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [authenticated, setAuthenticated] = useState(false);
  const onSubmit = (e) => {
    e.preventDefault();
    fetch("http://localhost:3006/addUser", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ email: email, password: password }),
    })
      .then(function (response) {
        return response.json();
      })
      .then((response) => {
        console.log(response);
        setAuthenticated(true);
      })
      .catch((err) => {
        console.log(err);
      });
  };

  return (
    <Router>
      <Switch>
        <router path="/" exact>
          <div>
            <form onSubmit={(e) => onSubmit(e)}>
              <label>email</label>
              <input
                name="email"
                type="email"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
              ></input>
              <label>password</label>
              <input
                name="password"
                type="password"
                value={password}
                onChange={(e) => setPassword(e.target.value)}
              ></input>
              <input type="submit" value="submit"></input>
            </form>
          </div>
          {authenticated ? <Redirect to="/auth" /> : null}
        </router>
        <Route path="/auth" exact>
          Authenticated
        </Route>
      </Switch>
    </Router>
  );
};

export default App;

在 React - 提交表单后,cookie 没有出现在开发工具中。

标签: javascriptnode.jsreactjsexpress

解决方案


  1. 在服务器中
  • 请启用 cors(安装 cors 库)。
app.use(
  cors({
    origin: true,
    credentials: true,
    optionsSuccessStatus: 200
}))
  • 添加会话配置。
app.use(
  session({
    key: 'sid',
    secret: Secret_String,
    resave: false,
    saveUninitialized: false,
    cookie: {
      path: '/',
      sameSite: 'none',
      httpOnly: true,
      secure: false,
      maxAge: 1000000000, // ten seconds, for testing
    },
    store: store, // postgres session store
  }),
);
  1. withcredentials在客户端中,调用 API 时必须使用选项。
  • Chrome 禁用了与 85.0 版本不同来源的 set-cookie。所以,set-cookie 是行不通的。您必须禁用 chrome 中的安全选项。请转到 chrome://flags -> 没有 SameSite 的 Cookie 必须是安全的 -> 禁用
  1. 在您的代码中
fetch("http://localhost:3006/addUser", {
      method: "POST",
      credentials: 'include',
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ email: email, password: password }),
})

推荐阅读