返回

React + Node + MongoDB:搭建个人主页项目的第一步

前端

项目架构

我们的项目架构主要分为前端和后端两部分。前端部分使用 React 框架,后端部分使用 Node.js 和 MongoDB 数据库。React 负责处理用户界面,而 Node.js 和 MongoDB 负责处理数据存储和检索。

登录验证

登录验证是任何项目中必不可少的环节。在我们的项目中,我们使用 JSON Web Token (JWT) 来实现登录验证。JWT 是一种安全且轻量级的身份验证机制,可以帮助我们验证用户的身份并授予他们相应的权限。

实现步骤

  1. 在前端,我们使用 React 的 Formik 库来创建登录表单。Formik 可以帮助我们轻松地管理表单状态和验证。
  2. 在后端,我们使用 Passport.js 库来处理用户认证。Passport.js 是一个功能强大的身份验证中间件,可以帮助我们轻松地将不同的认证策略集成到我们的项目中。
  3. 当用户提交登录表单时,我们会将表单数据发送到后端。后端会使用 Passport.js 来验证用户的身份。如果用户身份验证成功,后端会生成一个 JWT 并将其返回给前端。
  4. 前端收到 JWT 后,会将其存储在本地存储中。当用户访问需要身份验证的页面时,前端会将 JWT 发送到后端。后端会验证 JWT 的有效性,并授予用户相应的权限。

示例代码

// 前端代码

import React, { useState } from "react";
import Formik from "formik";
import axios from "axios";

const LoginForm = () => {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");

  const handleSubmit = async (values) => {
    setLoading(true);
    try {
      const response = await axios.post("/login", values);
      const jwt = response.data.jwt;
      localStorage.setItem("jwt", jwt);
      setLoading(false);
      window.location.href = "/";
    } catch (error) {
      setLoading(false);
      setError(error.response.data.message);
    }
  };

  return (
    <Formik
      initialValues={{ username: "", password: "" }}
      onSubmit={handleSubmit}
    >
      {({ values, errors, touched, handleChange, handleSubmit }) => (
        <form onSubmit={handleSubmit}>
          <label htmlFor="username">Username</label>
          <input
            type="text"
            name="username"
            value={values.username}
            onChange={handleChange}
          />
          {errors.username && touched.username && <div>{errors.username}</div>}

          <label htmlFor="password">Password</label>
          <input
            type="password"
            name="password"
            value={values.password}
            onChange={handleChange}
          />
          {errors.password && touched.password && <div>{errors.password}</div>}

          <button type="submit" disabled={loading}>
            Login
          </button>
        </form>
      )}
    </Formik>
  );
};

export default LoginForm;
// 后端代码

const passport = require("passport");
const jwt = require("jsonwebtoken");

passport.use(
  new LocalStrategy(
    { usernameField: "username", passwordField: "password" },
    async (username, password, done) => {
      const user = await User.findOne({ username });
      if (!user) {
        return done(null, false, { message: "Incorrect username or password." });
      }

      const isMatch = await user.comparePassword(password);
      if (!isMatch) {
        return done(null, false, { message: "Incorrect username or password." });
      }

      return done(null, user);
    }
  )
);

passport.serializeUser((user, done) => {
  done(null, user._id);
});

passport.deserializeUser(async (id, done) => {
  const user = await User.findById(id);
  done(null, user);
});

const generateJWT = (user) => {
  return jwt.sign({ id: user._id }, process.env.JWT_SECRET, {
    expiresIn: "1h",
  });
};

const login = async (req, res) => {
  const { username, password } = req.body;
  passport.authenticate("local", (err, user, info) => {
    if (err) {
      return res.status(400).json({ message: err.message });
    }

    if (!user) {
      return res.status(400).json({ message: info.message });
    }

    req.login(user, { session: false }, (err) => {
      if (err) {
        return res.status(400).json({ message: err.message });
      }

      const jwt = generateJWT(user);
      return res.status(200).json({ jwt });
    });
  })(req, res);
};

总结

在本文中,我们介绍了如何使用 React + Node + MongoDB 搭建个人主页项目的第一个部分:项目架构和登录验证实现。我们提供了详细的实现步骤和示例代码,希望能对您有所帮助。在下一篇博文中,我们将继续介绍该项目的其他部分,敬请期待!