发布于 2026-01-06 0 阅读
0

使用 MERN 技术栈构建电子商务网站 - 第 3 部分(身份验证和商品)

使用 MERN 技术栈构建电子商务网站 - 第 3 部分(身份验证和商品)

大家好!这是我们最近开始的MERN技术栈系列教程的第三部分。在第一部分中,我们学习了如何搭建项目,并了解了项目中将要用到的各种技术;在第二部分中,我们借助Mongoose和MongoDB开发了项目所需的所有模型。

注意:我会在 Medium 网站上发布所有文章的完整详细版本。这里我会先做个概述,并分章节提供各个页面的代码。这将会是一个包含 6-7 部分的系列文章。
所以,请点击这里前往 Medium 阅读全文(这些是友情链接,所以不用担心付费墙的问题。)

现在,在第三部分,我们将构建后端部分,它将通过借助 Express Router 构建 API 来处理我们 Web 应用程序中的身份验证和项目,我们还将定义一个自定义中间件函数来检查用户是否已通过身份验证。

为了保持代码的清晰简洁,我们将在根目录下创建一个名为 routes 的新文件夹。该文件夹将包含本项目所需的所有路由。

我们还会创建一个名为 controllers 的文件夹,用于存放所有在调用 API 端点时需要执行的函数。也就是说,我们将函数放在一个单独的文件夹中,然后在 routes 文件夹中导入它们以使用它们。

在 routes 文件夹内,我们将创建四个文件——auth、item、cart 和 order。这四个文件分别包含与身份验证、商品、购物车和订单相关的路由。

同样地,我们会在 controllers 文件夹内创建四个文件,分别对应 routes 文件夹中的每个文件。它们分别是 authControllers、itemControllers、cartControllers 和 orderControllers。

所以,现在我们将开始构建路由文件夹,这很简单,因为我们会将所有逻辑放在控制器文件夹中,而不是直接放在路由文件夹中。

路线

认证路由

const { Router } = require('express');
const authController = require('../controllers/authControllers');
const router = Router();
const auth = require('../middleware/auth');

router.post('/register', authController.signup);
router.post('/login', authController.login);
router.get('/user', auth, authController.get_user);

module.exports = router;
Enter fullscreen mode Exit fullscreen mode

物品路线

const { Router } = require('express');
const itemController = require('../controllers/itemControllers');
const router = Router();

router.get('/items', itemController.get_items);
router.post('/items',itemController.post_item);
router.put('/items/:id',itemController.update_item);
router.delete('/items/:id',itemController.delete_item);

module.exports = router;
Enter fullscreen mode Exit fullscreen mode

控制器

身份验证控制器

const User = require('../models/User');
const jwt = require('jsonwebtoken');
const config = require('config');
const bcrypt = require('bcrypt');

module.exports.signup = (req,res) => {
    const { name, email, password } = req.body;

    if(!name || !email || !password){
        res.status(400).json({msg: 'Please enter all fields'});
    }

    User.findOne({email})
    .then(user => {
        if(user) return res.status(400).json({msg: 'User already exists'});

        const newUser = new User({ name, email, password });

        // Create salt and hash
        bcrypt.genSalt(10, (err, salt) => {
            bcrypt.hash(password, salt, (err, hash) => {
                if(err) throw err;
                newUser.password = hash;
                newUser.save()
                    .then(user => {
                        jwt.sign(
                            { id: user._id },
                            config.get('jwtsecret'),
                            { expiresIn: 3600 },
                            (err, token) => {
                                if(err) throw err;
                                res.json({
                                    token,
                                    user: {
                                        id: user._id,
                                        name: user.name,
                                        email: user.email
                                    }
                                });
                            }
                        )
                    });
            })
        })
    })
}

module.exports.login = async (req,res) => {
    const { email, password } = req.body;
    if(!email || !password){
        res.status(400).json({msg: 'Please enter all fields'});
    }
    User.findOne({email})
        .then(user => {
            if(!user) return res.status(400).json({msg: 'User does not exist'});

            // Validate password
            bcrypt.compare(password, user.password)
                .then(isMatch => {
                    if(!isMatch) return res.status(400).json({ msg: 'Invalid credentials'});

                    jwt.sign(
                        { id: user._id },
                        config.get('jwtsecret'),
                        { expiresIn: 3600 },
                        (err, token) => {
                            if(err) throw err;
                            res.json({
                                token,
                                user: {
                                    id: user._id,
                                    name: user.name,
                                    email: user.email
                                }
                            });
                        }
                    )
                })
        })
}

module.exports.get_user = (req,res) => {
    User.findById(req.user.id)
        .select('-password')
        .then(user => res.json(user));
}
Enter fullscreen mode Exit fullscreen mode

项目控制器

const Item = require('../models/Item');

module.exports.get_items = (req,res) => {
    Item.find().sort({date:-1}).then(items => res.json(items));
}

module.exports.post_item = (req,res) => {
    const newItem = new Item(req.body);
    newItem.save().then(item => res.json(item));
}

module.exports.update_item = (req,res) => {
    Item.findByIdAndUpdate({_id: req.params.id},req.body).then(function(item){
        Item.findOne({_id: req.params.id}).then(function(item){
            res.json(item);
        });
    });
}

module.exports.delete_item = (req,res) => {
    Item.findByIdAndDelete({_id: req.params.id}).then(function(item){
        res.json({success: true});
    });
}
Enter fullscreen mode Exit fullscreen mode

身份验证中间件功能

const config = require('config');
const jwt = require('jsonwebtoken');

function auth(req, res, next) {
    const token = req.header('x-auth-token');

    // Check for token
    if(!token){
        return res.status(401).json({ msg: 'No token, authorization denied'});
    }

    try{
        // Verify token
        const decoded = jwt.verify(token, config.get('jwtsecret'));
        //Add user from payload
        req.user = decoded;
    next();
    } catch(e){
        res.status(400).json({ msg:'Token is not valid'});
    }
}

module.exports = auth;
Enter fullscreen mode Exit fullscreen mode

以上就是关于中间件功能的全部内容。我们已经完成了第三部分想要讲解的所有内容。在第四部分中,我们将讨论购物车和订单的路由和控制器。下一部分我们将使用 Stripe Checkout 处理支付。

感谢大家阅读本文。希望你们今天有所收获,学到了一些新知识。

要阅读完整教程,请前往 Medium 阅读完整文章

文章来源:https://dev.to/shubham1710/build-an-e-commerce-website-with-mern-stack-part-3-authentication-and-items-35gm