案例功能完善

更新时间: 2024-11-18 09:12:55

# 结合API接口

  • 新建 /router/api/account.js,内容和/router/index.js一致
  • 在app.js中应用 account.js
// 导入 account 接口路由文件
const accountRouter = require('./routes/api/account')
//...
//...
app.use('/api',accountRouter)
//...
1
2
3
4
5
6

# 获取账单接口

// 记账本的列表
router.get('/account', function(req, res, next) {
  // 获取所有的账单信息
  AccountModel.find().sort({time: -1}).then(data => {
    res.json({
        // 响应编号
        code: '0000',
        // 响应的信息
        msg: '读取成功',
        // 响应的数据
        data: data
    })
  }).catch(err => {
    res.json({
        code: '1001',
        msg: '读取失败',
        data: null
    })
  })
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 创建账单接口

// 新增记录
router.post('/account', (req, res) => {
  AccountModel.create({
    ...req.body,
    time: moment(req.body.time).toDate()
  }).then(data => {
    res.json({
        // 响应编号
        code: '0000',
        // 响应的信息
        msg: '创建成功',
        // 响应的数据
        data: data
    })
  }).catch(err => {
    res.json({
        code: '1002',
        msg: '创建失败',
        data: null
    })
  })
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 删除账单接口

// 删除记录
router.delete("/account/:id", (req, res) => {
  // 获取params的id参数  
  let id = req.params.id  
  // 删除
  AccountModel.deleteOne({_id: id}).then(data => {
    res.json({
        code: '0000',
        mgs: '删除成功',
        data: null
    })
  }).catch(err => {
    res.json({
        code: '1003',
        msg: '删除失败'
    })
  }) 
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 获取单条账单接口

// 获取单个账单信息
router.get('/account/:id',(req, res) => {
    // 获取 id 参数
    let {id} = req.params

    // 查询数据库
    AccountModel.findById(id).then(data => {
        res.json({
            code: '0000',
            msg: '读取成功',
            data: data
        })
    }).catch(err => {
        res.json({
            code: '1004',
            mgs: '读取失败',
            data: null
        })
    })
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 更新账单接口

router.patch('/account/:id',(req, res) => {
    // 获取id参数值
    let {id} = req.params  
    // 更新数据库 
    AccountModel.updateOne({_id:id}, req.body).then(data => {
        // 再次查询数据库,获取单条数据
        AccountModel.findById(id).then(data1 => {
            res.json({
                code: '0000',
                msg: '更新成功',
                data: data1
            })
        }).catch(err => {
            res.json({
                code: '1004',
                msg: '读取失败',
                data: null
            })
        })
    }).catch(err => {
        console.log(err)
        res.json({
            code:'1005',
            mgs:'更新失败',
            data: null
        })
    })
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 响应注册页面

  • 新建 views/auth/reg.ejs 模板
  • 新建 /routes/web/auth.js
var express = require('express') 
var router = express.Router()

// 注册  
router.get('/reg', (req, res) => {
    // 响应HTML内容
    res.render('auth/reg')
})

module.exports = router
1
2
3
4
5
6
7
8
9
10
  • 在app.js中引入auth.js并注册
//...
const authRouter = require('./routes/web/auth')

var app = express();

app.use('/', authRouter);
//...
module.exports = app;
1
2
3
4
5
6
7
8

# 注册用户

  • 新建用户模型对象 models/UserModel.js
// 导入 mongoose  
const mongoose = require('mongoose')  
// 创建文档的结构对象  
// 设置集合中文档的属性以及属性值的类型  
let UserSchema = new mongoose.Schema({
    username: String,
    password: String
})
// 创建模型对象,对文档操作的封装对象  
let UserModel = mongoose.model('users', UserSchema)  

// 暴露模型对象
module.exports = UserModel
1
2
3
4
5
6
7
8
9
10
11
12
13
  • 安装md5依赖 npm i md5
  • 新增注册接口
// 导入用户的模型  
const UserModel = require('../../models/UserModel')
const md5 = require('md5')  

//....

// 注册用户
router.post('/reg', (req, res) => {
    UserModel.create({...req.body, password: md5(req.body.password)}).then(data => {
        console.log(data)
        res.render('success', {msg:'注册成功', url:'/login'})
    }).catch(err => {
        res.status(500).send('注册失败,请稍后再试')
    })
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  • 修改模版
<form method="post" action="/reg">
    <div class="form-group">
        <label for="item">用户名</label>
        <input name="username" type="text" class="form-control" id="item" />
    </div>
    <div class="form-group">
        <label for="time">密码</label>
        <input name="password" type="password" class="form-control" id="time" />
    </div>
    <hr>
    <button type="submit" class="btn btn-primary btn-block">注册</button>
</form>
1
2
3
4
5
6
7
8
9
10
11
12

# 用户登录

  • 用户登录接口
// 登录路由  
router.get('/login',(req, res) => {
    res.render('auth/login')
})

// 登录
router.post('/login',(req, res) => {
    // 获取用户名和密码
    let {username, password} = req.body
    // 查询数据库
    UserModel.findOne({username: username, password: md5(password)}).then(data => {
        console.log(data)
        if(!data) {
            res.send("账号密码错误")
        }else{
            res.render('success', {msg:'登录成功', url: '/account'})
        }
    }).catch(err => {
        res.status(500).send('登录失败')
    })
})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  • 新建登录模版

# 写入session

  • 在app.js里配置session中间件
// app.js
// 导入 express-session  
const session = require('express-session')
const MongoStore = require('connect-mongo')  

// 导入配置项  
const {DBHOST, DBPORT, DBNAME} = require('./config/config')  

var app = express();

// 设置session的中间件
app.use(session({
  name:'sid', // 设置cookie的name,默认值是:connct.sid  
  secret: 'atguigu', // 参与加密的字符串(又称签名) 加盐  
  saveUninitialized: false, // 是否每次请求都设置一个cookie来存储session  
  resave: true, // 是否在每次请求时重新保存session 
  store: MongoStore.create({
    mongoUrl: `mongodb://${DBHOST}:${DBPORT}/${DBNAME}`
  }),
  cookie: {
    httpOnly: true, // 开启后前端无法通过js操作cookie 
    maxAge: 1000 * 60 * 20 // 这一条是控制 sessionID 的过期时间的 
  }
}))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  • 登录接口中保存session
// 登录
router.post('/login',(req, res) => {
    // 获取用户名和密码
    let {username, password} = req.body
    // 查询数据库
    UserModel.findOne({username: username, password: md5(password)}).then(data => {
        console.log(data)
        if(!data) {
            res.send("账号密码错误")
        }else{
            // 写入session  
            req.session.username = data.username
            req.session._id = data._id
            res.render('success', {msg:'登录成功', url: '/account'})
        }
    }).catch(err => {
        res.status(500).send('登录失败')
    })
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 用户登录检测

  • 检测登录中间件
// middlewares/checkLoginMiddleware.js
// 声明中间件检测登录  
let checkLoginMiddleware = (req, res, next) => {
    // 判断 
    if(!req.session.username) {
        return res.redirect('login')
    }
    next()
}

module.exports = checkLoginMiddleware
1
2
3
4
5
6
7
8
9
10
11
  • 使用中间件



 


 







 




 













 















//...

// 导入中间件检测登录
let checkLoginMiddleware = require('../../middlewares/checkLoginMiddleware')

// 记账本的列表
router.get('/account', checkLoginMiddleware, function(req, res, next) {
  // 获取所有的账单信息
  AccountModel.find().sort({time: -1}).then(data => {
    res.render('list',{accounts: data, moment: moment})
  })
});

// 添加记录
router.get('/account/create',checkLoginMiddleware,function(req, res, next) {
  res.render('create')
})

// 新增记录
router.post('/account',checkLoginMiddleware, (req, res) => {
  AccountModel.create({
    ...req.body,
    time: moment(req.body.time).toDate()
  }).then(data => {
    res.render('success', {msg: '添加成功哦~', url:'/account'})
  }).catch(err => {
    console.log(err)
    res.status(500).send('插入失败~')
    return
  })
})

// 删除记录
router.get("/account/:id",checkLoginMiddleware, (req, res) => {
  // 获取params的id参数  
  let id = req.params.id  
  // 删除
  AccountModel.deleteOne({_id: id}).then(data => {
    // 提醒
    res.render('success', {msg: '删除成功~', url:'/account'})
  }).catch(err => {
    res.status(500).send('删除失败~~')
  })
  
})

module.exports = router;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

# 退出登录

  • 修改模板,在列表模板上加上退出按钮
<div class="row text-right">
    <div class="col-xs-12" style="padding-top:20px;">
        <a href="/logout" class="btn btn-danger">退出</a>
    </div>
</div>
1
2
3
4
5
  • 退出接口
// 退出登录
router.get('/logout',(req, res) => {
    // 销毁session
    req.session.destroy(() => {
        res.render('success', {msg: '退出成功', url: '/login'})
    })
})
1
2
3
4
5
6
7

# 首页和404页面

  • 首页路由规则
// 添加首页路由规则
router.get('/',(req, res) => {
  res.redirect('/account')
})
1
2
3
4
  • 新建404页面模板
  • app.js中应用404页面
// catch 404 and forward to error handler
app.use(function(req, res, next) {
  // 响应 404
  res.render('404')
});
1
2
3
4
5

# 登录响应token

  • 修改登录接口
// router/api/auth.js
// 登录
router.post('/login',(req, res) => {
    // 获取用户名和密码
    let {username, password} = req.body
    // 查询数据库
    UserModel.findOne({username: username, password: md5(password)}).then(data => {
        console.log(data)
        if(!data) {
            res.json({
                code: '2002',
                msg: '用户名或密码错误',
                data: null
            })
        }else{
            // 创建当前用户的token  
            let token = jwt.sign({
                username: data.username,
                _id: data._id
            },'atguigu',{
                expiresIn: 60 * 20
            })
            // 响应token  
            res.json({
                code: '0000',
                msg: '登录成功',
                data: token
            })
        }
    }).catch(err => {
        res.json({
            code: '2001',
            msg: '数据库读取失败',
            data: null
        })
    })
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  • 在app.js中去注册
const authApiRouter = require('./routes/api/auth')
app.use('/api',authApiRouter)
1
2

# token校验

  • token校验中间件
// middleware/checkTokenMiddleware.js
const jwt = require('jsonwebtoken')

const checkTokenMiddleware = (req, res, next) => {
    // 获取 token  
    let token = req.get('token')
    if(!token) {
        return res.json({
        code: '2003',
        msg: 'token缺失',
        data: null
        })
    }
    // 校验 token  
    jwt.verify(token, 'atguigu', (err, data) => {
        // 检测 token 是否正确
        if(err) {
        return res.json({
            code: '2004',
            msg: 'token校验失败',
            data: null
        })
        }
        // 如果token校验成功 
        next()
    })
}

module.exports = checkTokenMiddleware
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  • 使用中间件
//...

// 校验token中间件  
const checkTokenMiddleware = require("../../middlewares/checkTokenMiddleware")

// 记账本的列表
router.get('/account', checkTokenMiddleware, function(req, res, next) {
  //...
});

// 新增记录
router.post('/account', checkTokenMiddleware, (req, res) => {
  //...
})

// 删除记录
router.delete("/account/:id",checkTokenMiddleware, (req, res) => {
  //...
})

// 获取单个账单信息
router.get('/account/:id',checkTokenMiddleware,(req, res) => {
   //..
})

// 更新单个账单信息  
router.patch('/account/:id',checkTokenMiddleware,(req, res) => {
    //...
})

module.exports = router;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# token功能完善

























 







const jwt = require('jsonwebtoken')
const {secret} = require('../config/config') 

const checkTokenMiddleware = (req, res, next) => {
    // 获取 token  
    let token = req.get('token')
    if(!token) {
        return res.json({
        code: '2003',
        msg: 'token缺失',
        data: null
        })
    }
    // 校验 token  
    jwt.verify(token, secret, (err, data) => {
        // 检测 token 是否正确
        if(err) {
            return res.json({
                code: '2004',
                msg: 'token校验失败',
                data: null
            })
        }
        // 保存用户的信息
        req.user = data
        // 如果token校验成功 
        next()
    })
}

module.exports = checkTokenMiddleware
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 本地域名配置

所谓本地域名就是只能在本机使用的域名,一般在开发阶段使用

# 操作流程

编辑文件 C:\Windows\System32\drivers\etc\hosts

127.0.0.1 www.baidu.com

如果修改失败,可以修改该文件的权限

# 原理

在地址栏输入域名之后,浏览器会先进行DNS(Domain Name System)查询,获取该域名对应的IP地址请求会发送到DNS服务器,可以根据域名返回IP地址

可以通过 ipconfig/all 查看本机的DNS服务器

host文件也可以设置域名与IP的映射关系,在发送请求前,可以通过该文件获取域名的IP地址