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('刪除失敗'))
})
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章