从零开始用react + tailwindcs + express + mongodb实现一个聊天程序(三) 实现注册 登录接口

1.划分文件夹

在src目录下创建controllers middleware models routes

controllers 放具体的方法 signup login

middleware 里面是中间件 请求的验证

models 放对象实体

routes 处理访问路径像/signup /login 等等

2. 接口开发

系统的主要 有用户认证 和 消息 2种类型服务

在index下面添加如下代码

javascript 复制代码
import authRoutes from './routes/auth.route.js'
import bodyParser from 'body-parser'
import cookieParser from 'cookie-parser'

// 解决req.body undefined问题
app.use(cookieParser())
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
// 实现signup 注册接口 认证
app.use('/api/auth', authRoutes)

/api/auth 是路由前缀 authRoutes是 处理请求的路由

在刚刚建好的routes文件夹下 创建auth.route.js 内容如下

javascript 复制代码
import express from 'express';

import {signUp, login} from "../controllers/auth.controller.js"


const router = express.Router();

router.post('/signup', signUp)
router.post('/login', login)

export default router;

在models下创建user.model.js 创建user对象schema 作用是和数据库关联 (用法详见mongodb教程)

javascript 复制代码
import mongoose from "mongoose";
const userSchema = new mongoose.Schema({
    email: {
        type: String,
        required: true,
        unique: true
    },
    password: {
        type: String,
        required: true,
        minlenght: 6
    },
    userName: {
        type: String,
        required: true
    },
    profilePic: {
        type: String,
        default: ''
    }
}, {timestamps: true});

const User = mongoose.model('User', userSchema);

export default User;

在lib文件夹下创建 util.js

javascript 复制代码
import jwt from 'jsonwebtoken'

export const generateToken = (userId,res) => {
    
    // 7天有效期
    const token = jwt.sign({userId},process.env.JWT_SECRET,{expiresIn:'7d'})

    res.cookie('jwt',token,{
        maxAge: 1000 * 60 * 60 * 24 * 7,
        httpOnly: true,
        sameSite: "strict",
        secure: process.env.NODE_ENV !== 'development'
    })

    return token
}

在 /server/.env下 加 JWT_SECRET=mysecret 配置

在controllers文件夹下创建auth.controller.js 写我们的接口逻辑

javascript 复制代码
import { generateToken } from "../lib/util.js";
import User from "../models/user.model.js";
import bcrypt from "bcryptjs";

// 实现signup接口
export const signUp = async (req, res) => {
    const { userName,password, email } = req.body
    // TODO: implement signup
    // 判断字段是否全部输入
    try {
        if (!userName || !password || !email) {
            return res.status(400).json({ message: '缺失字段' })
        }
        // 判断密码长度
        if (password.length < 6) {
            return res.status(400).json({ message: '密码长度不能小于6位' })
        }
        // 判断用户名是否已存在
        const user = await User.findOne({ email })

        if(user) {
            return res.status(400).json({ message: '邮箱已存在' })
        }
        // 密码加密
        const salt = await bcrypt.genSalt(10)
        const hashPassword = await bcrypt.hash(password,salt)

        // 创建用户
        const newUser = new User({
            userName,
            email,
            password: hashPassword
        })
        // 保存用户
        if(newUser) {
            generateToken(newUser._id,res)
            await newUser.save()

            res.status(201).json({
                _id: newUser._id,
                userName: newUser.userName,
                email: newUser.email,
                profilePic: newUser.profilePic,
            })
        }
    } catch (err) {
        return res.status(500).json({ message: '内部服务器错误' })
    }
}

// 登录
export const login = async (req, res) => {
    const {password, email} = req.body
    try {
        const user = await User.findOne({ email })
        if (!user) {
            return res.status(400).json({ message: '认证失败' })
        }

        // 比较密码
        const isMatch = await bcrypt.compare(password, user.password)
        if (!isMatch) {
            return res.status(400).json({ message: '认证失败' })
        }

        generateToken(user._id,res)
        res.status(200).json({
            _id: user._id,
            userName: user.userName,
            email: user.email,
            profilePic: user.profilePic
        })
    } catch (err) {
        return res.status(500).json({ message: '内部服务器错误' })
    }
}

// 退出
export const logout = async (req, res) => {
    try {
        res.cookie("jwt","", {maxAge:0})
        res.status(200).json({ message: '退出成功' })
    } catch (err) {
        return res.status(500).json({ message: '内部服务器错误' })
    }
}

3. postman测试接口

1.signup 注册接口

密码输入1 小于6位

注册成功返回用户信息

查看数据库 有我们刚才注册的信息 并且密码也已加密

2.login 登录接口

返回用户信息 登录成功

3. logout 登出

提示退出成功

以上就是本篇内容 下篇我们实现前端 页面 实现注册 登录页面 并和后端接口联调。如有问题评论私信都可以联系我 一起交流

相关推荐
有味道的男人2 小时前
搜好货平台关键词商品搜索接口:分页容错与商品数据轻量化提取方案
服务器·前端·javascript
lovingsoft3 小时前
Chrome Lighthouse 详解
前端·chrome
Qlly3 小时前
全栈工程师怎么接需求?从一句「加个功能」聊到能开发、能验收
前端·后端
马可家的菠萝3 小时前
你的微信“文件传输助手”,是不是已经成了第二个网盘?
前端·后端·架构
略略略啦3 小时前
Vibe Coding 基于Spec DD和TDD的实践指南
前端
shmily麻瓜小菜鸡3 小时前
前端实现图片与PDF文字识别敏感信息打码方案
前端·pdf·状态模式
打工仔折腾 AI4 小时前
LangChain 工具调用实战:从 Tool 定义到 Agent 执行链路拆解
java·前端·人工智能·后端·python·langchain·ai agent 实战
汉堡大王95274 小时前
单次输出拉到100万Token:拆完 Gemini 4 Argon 的续写协议,才看懂谷歌这7个月在憋什么
前端·人工智能·后端
看浪的路人4 小时前
第9讲:大模型应用监控与可观测性——OpenTelemetry + Prometheus + Grafana 全链路追踪
java·前端·spring
内存过载4 小时前
用表格模拟甘特图:项目排期的土办法
前端·低代码