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('刪除失敗'))
})