vue-cli3 + express + mongodb小型全栈项目(一)

1、express搭建服务器

1、新建一个项目文件夹,node_app,进去文件夹后,使用命令npm init 初始化项目。
在这里插入图片描述
注意:这里将入口文件改为了server.js.
2、安装express,全局安装nodemon。
3、项目根目录新建server.js文件,内容如下:

const express = require('express');
const app  = express();

const port = process.env.PORT || 5000;

app.get('/',(req,res)=>{
    res.send("hello express")
})

app.listen(port,()=>{
    console.log(`Server running on port ${port}`);
})

4、修改package.json文件 ,增加两个脚本命令。

 "scripts": {
    "server": "nodemon server.js",
    "start":"node server.js"
  },

5、浏览器打开http://localhost:5000/。
在这里插入图片描述
说明express服务器搭建成功了。

2、连接MongoDB数据库

1、下载mongoose
2、根目录新建config文件夹 新建keys.js文件
keys.js文件内容如下:

module.exports = {
    mongonURI:"mongodb://localhost:27017/test"
}

3、在server.js文件中添加如下代码

const mongoose = require('mongoose')


const users = require('./routers/api/users')


const db = require("./config/keys").mongonURI

mongoose.connect(db)
    .then(()=>{
   	 		console.log("mongodb connet"); 
		})
	.catch(err=>console.log(err))

在这里插入图片描述
表示连接成功。
4、创建数据模型
根目录下新建models文件夹 新建User.js文件
User.js文件内容如下

const mongoose = require("mongoose")

const Schema = mongoose.Schema;

const UserSchema = new Schema({
    name:{
        type:String,
        required:true
    },
    email:{
        type:String,
        required:true
    },
    password:{
        type:String,
        required:true
    },
    avatar:{
        type:String
    },
    date:{
        type:Date,
        default:Date.now
    }
})
module.exports = User = mongoose.model('users',UserSchema)

3、创建路由

根目录下新建routerswen文件夹,新建api文件夹,新建users.js 文件
新建users.js 文件内容如下:

const express = require("express");

const router = express.Router();

// get请求 /api/users/test
router.get('/test',(req,res)=>{
    res.json({
        msg:"test msg"
    })
})

module.exports = router;

server.js文件添加如下代码


const users = require('./routers/api/users')
app.use('/api/users',users)

浏览器打开http://localhost:5000/api/users/test
在这里插入图片描述

4、创建注册接口并存储到数据库

4.1 安装body-parser,用于解析POST请求的body数据。然后在server.js中添加如下代码:

const bodyParser = require('body-parser')
// ...省略已有代码
// 使用 body-parser 中间件
app.use(bodyParser.urlencoded({extended:false}))
app.use(bodyParser.json())

4.2 安装bcrypt,用于加密密码。
4.3 安装gravatar,用于生成头像的。全球公认头像gravatar
在此网站可以注册一个账号,并上传头像。

4.4 在user.js文件中添加如下代码:

const bcrypt = require('bcrypt')
const gravatar = require('gravatar')


router.post('/register',(req,res)=>{
   console.log(req.body);
   //查询数据库中是否有邮箱
   User.findOne({email:req.body.email}).then(user =>{
       if (user) {
           return res.status(400).json({email:"该邮箱已经被注册"})
       }else{
           const newUser = new User({
               name:req.body.name,
               email:req.body.email,
               avatar:gravatar.url(req.body.email,{s:'200',r:'pg',d:'mm'}),//拉取头像 如果没有在全球公认头像网站上注册的话将会生成一个默认的头像
               password:req.body.password
           })
           // 加密密码
           bcrypt.genSalt(10,(err,salt)=>{
            bcrypt.hash(newUser.password,salt,(err,hash)=>{
                   if(err) throw err;
                   newUser.password = hash;
                   newUser.save()
                    .then(user=>res.json(user))
                    .catch(err=>console.log(err));
               })
           })
       }
   })
})

4.5 在postman中测试一下
在这里插入图片描述
查看下MongoDB中的数据,可以看到这条记录已经添加到库里了。
在这里插入图片描述

5 创建登录接口并使用JWT返回一个token

5.1 安装jsonwebtoken,用于生成一个token

5.2 config/keys.js文件增加一个secret

module.exports = {
    mongonURI:"mongodb://localhost:27017/test",
    secretOrKey:' secret' //用于生成token
}

5.3 users.js文件增加一个登录接口

const jwt = require('jsonwebtoken')

const keys = require('./../../config/keys')
// 登录接口
router.post('/login',(req,res)=>{
    const {email,password} = req.body;
    // 查询数据库
    User.findOne({email}).then(user=>{
        if (!user) {
            return res.status(404).json({email:"用户不存在"})
        }
        // 密码匹配
        bcrypt.compare(password,user.password).then(isMatch=>{
            if (isMatch) {
                // 加密规则 加密名字 过期时间 回调
                const rule = {id:user._id,name:user.name}
                jwt.sign(rule,keys.secretOrKey,{expiresIn:3600},(err,token)=>{
                    if (err) {
                        throw err
                    }
                    res.json({
                        success:true,
                        token
                    })
                })
            }else{
              return  res.status(400).json({msg:'密码错误'})
            }
        })
    })
})

5.4 postman测试

在这里插入图片描述

6、使用passport-jwt验证token

6.1 安装passport、 passport-jwt。
6.2 config文件夹下新建passport.js文件,内容如下

const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const mongoose = require('mongoose');
const User = mongoose.model('users');
const keys = require('./../config/keys');

const opts = {}
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = keys.secretOrKey;

module.exports = passport =>{
    passport.use(new JwtStrategy(opts,(jwt_payload,done)=>{
        User.findById(jwt_payload.id).then(user=>{
            if (user) {
                return done(null,user)
            }
            return done(null,false)
        }).catch(err=>{})
    }))
}

6.3 server.js文件增加如下代码


const passport = require('passport')

//初始化
app.use(passport.initialize())
require('./config/passport')(passport)


6.4 user.js文件修改如下

const express = require("express");

const router = express.Router();
const bcrypt = require('bcrypt')
const gravatar = require('gravatar')
const jwt = require('jsonwebtoken')
const User = require('./../../models/User')
const keys = require('./../../config/keys')
const passport = require('passport')

// get请求 /api/users/test
router.get('/test',(req,res)=>{
    res.json({
        msg:"test msg"
    })
})
router.post('/register',(req,res)=>{
   console.log(req.body);
   //查询数据库中是否有邮箱
   User.findOne({email:req.body.email}).then(user =>{
       if (user) {
           return res.status(400).json({email:"该邮箱已经被注册"})
       }else{
           const newUser = new User({
               name:req.body.name,
               email:req.body.email,
               avatar:gravatar.url(req.body.email,{s:'200',r:'pg',d:'mm'}),
               password:req.body.password
           })
             // 加密密码
           bcrypt.genSalt(10,(err,salt)=>{
            bcrypt.hash(newUser.password,salt,(err,hash)=>{
                   if(err) throw err;
                   newUser.password = hash;
                   newUser.save()
                    .then(user=>res.json(user))
                    .catch(err=>console.log(err));
               })
           })
       }
   })
})

// 登录接口
router.post('/login',(req,res)=>{
    const {email,password} = req.body;
    // 查询数据库
    User.findOne({email}).then(user=>{
        if (!user) {
            return res.status(404).json({email:"用户不存在"})
        }
        // 密码匹配
        bcrypt.compare(password,user.password).then(isMatch=>{
            if (isMatch) {
                // 加密规则 加密名字 过期时间 回调
                const rule = {id:user._id,name:user.name}
                jwt.sign(rule,keys.secretOrKey,{expiresIn:3600},(err,token)=>{
                    if (err) {
                        throw err
                    }
                    res.json({
                        success:true,
                        token:'Bearer '+token
                    })
                })
            }else{
              return  res.status(400).json({msg:'密码错误'})
            }
        })
    })
})

//jwt验证token
router.get('/current',passport.authenticate('jwt',{session:false}),(req,res)=>{
    res.json({
        id:req.user.id,
        name:req.user.name,
        email:req.user.email
    })
})
module.exports = router;

6.5 postman 测试

在这里插入图片描述

7、增加身份字段

增加一个字段,用于标识用户身份。
7.1 User.js文件UserSchema增加一个字段identity

const UserSchema = new Schema({
    name:{
        type:String,
        required:true
    },
    email:{
        type:String,
        required:true
    },
    password:{
        type:String,
        required:true
    },
    avatar:{
        type:String
    },
    identity:{
        type:String,
        required:true
    },
    date:{
        type:Date,
        default:Date.now
    }
})

7.2 users.js文件注册、登录、验证接口都做相应调整。

const express = require("express");

const router = express.Router();
const bcrypt = require('bcrypt')
const gravatar = require('gravatar')
const jwt = require('jsonwebtoken')
const User = require('./../../models/User')
const keys = require('./../../config/keys')
const passport = require('passport')

router.post('/register',(req,res)=>{
   console.log(req.body);
   //查询数据库中是否有邮箱
   User.findOne({email:req.body.email}).then(user =>{
       if (user) {
           return res.status(400).json("该邮箱已经被注册")
       }else{
           const newUser = new User({
               name:req.body.name,
               email:req.body.email,
               avatar:gravatar.url(req.body.email,{s:'200',r:'pg',d:'mm'}),
               password:req.body.password,
               identity:req.body.identity
           })
             // 加密密码
           bcrypt.genSalt(10,(err,salt)=>{
            bcrypt.hash(newUser.password,salt,(err,hash)=>{
                   if(err) throw err;
                   newUser.password = hash;
                   newUser.save()
                    .then(user=>res.json(user))
                    .catch(err=>console.log(err));
               })
           })
       }
   })
})

// 登录接口
router.post('/login',(req,res)=>{
    const {email,password} = req.body;
    // 查询数据库
    User.findOne({email}).then(user=>{
        if (!user) {
            return res.status(404).json("用户不存在")
        }
        // 密码匹配
        bcrypt.compare(password,user.password).then(isMatch=>{
            if (isMatch) {
                // 加密规则 加密名字 过期时间 回调
                const rule = {
                    id:user._id,
                    name:user.name,
                    avatar:user.avatar,
                    identity:user.identity
                }
                jwt.sign(rule,keys.secretOrKey,{expiresIn:3600},(err,token)=>{
                    if (err) {
                        throw err
                    }
                    res.json({
                        success:true,
                        token:'Bearer '+token
                    })
                })
            }else{
              return  res.status(400).json('密码错误')
            }
        })
    })
})

//jwt验证token
router.get('/current',passport.authenticate('jwt',{session:false}),(req,res)=>{
    res.json({
        id:req.user.id,
        name:req.user.name,
        email:req.user.email,
        identity:req.user.identity
    })
})
module.exports = router;

8、增加数据的接口

8.1 models文件夹下新建Profile.js文件,内容如下

const mongoose = require("mongoose")

const Schema = mongoose.Schema;

const ProfileSchema = new Schema({
    type:{
        type:String
    },
    describe:{
        type:String
    },
    income:{
        type:String,
        required:true
    },
    expend:{
        type:String,
        required:true
    },
    cash:{
        type:String,
        required:true
    },
    remark:{
        type:String
    },
    date:{
        type:Date,
        default:Date.now
    }
})
module.exports = Profile = mongoose.model('profile',ProfileSchema)

8.2 routers下api文件夹下新建profiles.js文件

const express = require("express");
const router = express.Router();
const passport = require('passport')
const Profile = require('./../../models/Profile')


router.post("/add",passport.authenticate('jwt',{session:false}),(req,res)=>{
    const profileFields = {};
    if(req.body.type) profileFields.type =  req.body.type;
    if(req.body.describe) profileFields.describe =  req.body.describe;
    if(req.body.income) profileFields.income =  req.body.income;
    if(req.body.expend) profileFields.expend =  req.body.expend;
    if(req.body.cash) profileFields.cash =  req.body.cash;
    if(req.body.remark) profileFields.remark =  req.body.remark;

    new Profile(profileFields).save().then(profile=>{
        res.json(profile)
    })
})
module.exports = router;

8.3 server.js文件增加如下代码


const profiles = require('./routers/api/profiles')

app.use('/api/profiles',profiles)

8.4 postman测试
在这里插入图片描述
注意:这里需要在请求头上添加Authorization,就是登录接口返回的token
在这里插入图片描述

9、增加获取所有数据信息、获取单条数据信息、编辑信息、删除信息的接口

profiles.js文件增加如下代码:

// 获取所有信息
router.get('/',passport.authenticate('jwt',{session:false}),(req,res)=>{
    Profile.find().then(profile=>{
        if (!profile) {
           return res.status(404).json('没有内容') 
        }
        res.json(profile)
    }).catch(err=>{
        res.status(404).json(err) 
    })
})
// 获取单个信息
router.get('/:id',passport.authenticate('jwt',{session:false}),(req,res)=>{
    Profile.findOne({_id:req.params.id}).then(profile=>{
        if (!profile) {
           return res.status(404).json('没有内容') 
        }
        res.json(profile)
    }).catch(err=>{
        res.status(404).json(err) 
    })
})
// 编辑
router.post("/edit/id",passport.authenticate('jwt',{session:false}),(req,res)=>{
    const profileFields = {};
    if(req.body.type) profileFields.type =  req.body.type;
    if(req.body.describe) profileFields.describe =  req.body.describe;
    if(req.body.income) profileFields.income =  req.body.income;
    if(req.body.expend) profileFields.expend =  req.body.expend;
    if(req.body.cash) profileFields.cash =  req.body.cash;
    if(req.body.remark) profileFields.remark =  req.body.remark;

    Profile.findByIdAndUpdate(
        {_id:req.params.id},
        {$set:profileFields},
        {new:true})
    .then(profile=>{
        res.json(profile)
    })
})
//删除
router.delete('/delete/:id',passport.authenticate('jwt',{session:false}),(req,res)=>{
    Profile.findOneAndRemove({_id:req.params.id}).then(profile=>{
        profile.save().then(profile=>res.json(profile))
    }).catch(err=>res.status(404).json('删除失败'))
})
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章