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('删除失败'))
})