Node.js项目(二)

1.删除用户(backend)

  • 路由routes/users.js
const { signup, list, remove } = require('../controllers/users')

router.delete('/', remove)
//...
  • 控制层:controllers/users.js
//删除用户
const remove = async (req, res, next) => {

    res.set('content-type', 'application/json; charset=utf-8')
    const { id } = req.body
    let result = await usersModel.remove(id)
    console.log(result)
    if (result) {
        res.render('succ', {
            data: JSON.stringify({
                message: '用户删除成功!'
            })
        })
    } else {
        res.render('fail', {
            data: JSON.stringify({
                message: '用户删除失败!'
            })
        })
    }


}
//...
exports.remove = remove

  • M层:modules/users.js
const remove = (id) => {
    // return Users.deleteOne({ _id: id })
    console.log(id)
    return Users.findByIdAndRemove(id)
}
//...
exports.remove = remove

2.删除用户(frontend)

controllers/index.js



const index = (router) => {
    return async (req, res, next) => {
        //渲染首页
        res.render(htmlIndex)
        //window.resize(),让页面撑满整个屏幕
        $(window, '.wrapper').resize()

        //填充用户列表
        $('#content').html(usersTpl())
        //这里通过事件代理删除用户
        $('#users-list').on('click', '.remove', function () {
            console.log($(this).data('id'))
            $.ajax({
                url: '/api/users',
                type: 'delete',
                data: {
                    id: $(this).data('id')
                },
                success() {
                    _loadData()
                    // _pagination(dataList)
                }
            })
        })

        //初次渲染list
        _loadData()
        _list(1)


        //点击保存,提交表单
        $('#users-save').html(usersTpl())

    }
}

//...

3.抽离当前页面与完善分页

  • frontend/controllers/index.js
//es6导入模块的方法
// import router from '../routers'
import indexTpl from '../views/index.art'
import signinTpl from '../views/signin.art'
import usersTpl from '../views/users.art'
import usersListTpl from '../views/users-list.art'
import userListPageTpl from '../views/users-pages.art'


const htmlIndex = indexTpl({})
const htmlSignin = signinTpl({})
const pageSize = 5
let currentPage = 1
let dataList = []
const _handleSubmit = (router) => {
    return (e) => {
        e.preventDefault()
        router.go('/index')

    }
}

const _loadData = () => {
    return $.ajax({
        url: '/api/users',
        async: false,
        success(result) {
            dataList = result.data
            //分页
            _pagination(result.data)
            _list(currentPage)
        }
    })
}
//显示分页效果
const _pagination = (data) => {

    const total = data.length
    //往上取整
    const pagesCount = Math.ceil(total / pageSize)
    const pageArray = new Array(pagesCount)

    const htmlPage = userListPageTpl({
        pageArray
    })

    $('#users-page').html(htmlPage)
    //默认添加第一个
    // $('#users-page-list li:nth-child(2').addClass('active')
    // $('#users-page-list li:not(:first-child , :last-child)').on('click', function () {
    //     const index = $(this).index()
    //     $(this).addClass('active').siblings().removeClass('active')
    //     _list(index)
    //     currentPage = index
    // })
    _setPageActive(currentPage)


}

//装填list数据
const _list = (pageNo) => {

    let start = (pageNo - 1) * pageSize
    $('#users-list').html(usersListTpl({
        //截取数据
        data: dataList.slice(start, start + pageSize)
    }))

}



const signin = (router) => {
    return (req, res, next) => {
        res.render(htmlSignin)
        $('#signin').on('submit', _handleSubmit(router))

    }
}

const index = (router) => {
    return async (req, res, next) => {
        //渲染首页
        res.render(htmlIndex)
        //window.resize(),让页面撑满整个屏幕
        $(window, '.wrapper').resize()

        //填充用户列表
        $('#content').html(usersTpl())

        //这里通过事件代理删除用户
        $('#users-list').on('click', '.remove', function () {
            console.log($(this).data('id'))
            $.ajax({
                url: '/api/users',
                type: 'delete',
                data: {
                    id: $(this).data('id')
                },
                success() {
                    _loadData()
                    // _pagination(dataList)
                    const isLastpage = Math.ceil(dataList.length / pageSize) === currentPage
                    const restOne = dataList.length % pageSize === 1
                    const notPageFirst = currentPage > 0
                    console.log(currentPage)
                    if (isLastpage && restOne && notPageFirst) {
                        currentPage--
                    }
                    console.log(currentPage)
                }
            })
        })
        $('#users-page').on('click', '#users-page-list li:not(:first-child , :last-child)', function () {
            const index = $(this).index()
            _list(index)
            // console.log(index)
            currentPage = index
            _setPageActive(index)
        })
        $('#users-page').on('click', '#users-page-list li:first-child ', function () {

            if (currentPage > 1) {
                currentPage--
                _list(currentPage)
                _setPageActive(currentPage)
            }

        })
        $('#users-page').on('click', '#users-page-list li:last-child ', function () {

            if (currentPage < Math.ceil(dataList.length / pageSize)) {
                currentPage++
                _list(currentPage)
                _setPageActive(currentPage)
            }

        })

        //初次渲染list
        _loadData()
        _list(1)


        //点击保存,提交表单
        $('#users-save').html(usersTpl())

    }
}

const _setPageActive = (index) => {
    // $(this).addClass('active').siblings().removeClass('active')
    $('#users-page #users-page-list li:not(:first-child , :last-child)')
        .eq(index - 1)
        .addClass('active')
        .siblings()
        .removeClass('active')
}

const _signup = () => {
    const $btnClose = $('#users-close')

    //提交表单
    const data = $('#users-form').serialize()
    console.log(data)

    $.ajax({
        url: '/api/users',
        type: 'post',
        data,
        sucdess: async (res) => {
            console.log(res)
            //提交数据后渲染
            _loadData()
            _list(1)
        }
    })
    //单击关闭模拟框
    $btnClose.click()

}

const signup = () => {

}

export {
    signin,
    index
}

lagou-admin/backend/utils/tools.js

const bcrypt = require('bcrypt')

exports.hash = (myPlaintextPassword) => {

    return new Promise((resolve, reject) => {
        // bcrypt.hash(myPlaintextPassword, 10, function (err, hash) {

        //     if (err) {
        //         reject(err)
        //     }
        //     resolve(hash)
        // })
        bcrypt.genSalt(10, function (err, salt) {
            bcrypt.hash(myPlaintextPassword, salt, function (err, hash) {

                if (err) {
                    reject(err)
                }
                resolve(hash)
            })
        })
    });
}

exports.compare = (myPlaintextPassword, hash) => {
    return new Promise((resolve, reject) => {
        bcrypt.compare(myPlaintextPassword, hash, function (err, result) {
            resolve(result)
        })
    })
}

4.登出

frontend/controllers/index.js

import router from '../routers/index'
//...

const index = (router) => {
    	//...
        //登出事件绑定
        $('#users-signout').on('click', (e) => {

            //默认状态下a链接有个事件会自动触发,我们要么在a链接中的href属性的值#改为javascript:void(0),要么阻止默认事件的传播:e.preventDefault()
            e.preventDefault()
            router.go('/signin')
            console.log(0)
        })

        //初次渲染list
        _loadData()
        _list(1)


        //点击保存,提交表单
        $('#users-save').html(usersTpl())

    }
}

//...

frontend/src/app.js

//载入css
import './assets/common.css'

//载入路由
import router from './routers'
// router.go('/index')
router.go('/')

5.验证登录–backend

  • backend这里我们使用一个第三方插件库:randomstringyarn add randomstring -S

routes/users.js

//....
//登录
router.post('/signin', signin)


module.exports = router;

tool.js

const bcrypt = require('bcrypt')

exports.hash = (myPlaintextPassword) => {

    return new Promise((resolve, reject) => {
        // bcrypt.hash(myPlaintextPassword, 10, function (err, hash) {

        //     if (err) {
        //         reject(err)
        //     }
        //     resolve(hash)
        // })
        bcrypt.genSalt(10, function (err, salt) {
            bcrypt.hash(myPlaintextPassword, salt, function (err, hash) {

                if (err) {
                    reject(err)
                }
                resolve(hash)
            })
        })
    });
}

exports.compare = (myPlaintextPassword, hash) => {
    return new Promise((resolve, reject) => {
        bcrypt.compare(myPlaintextPassword, hash, function (err, result) {
            resolve(result)
        })
    })
}

backend/controllers/index.js

//...
const randomstring = require('randomstring')

//用户登录
const signin = async (req, res, next) => {
    const { username, password } = req.body

    let result = await usersModel.findUser(username)

    //验证用户是否是合法用户并且密码是否正确
    if (result) {
        let { password: hash } = result
        let compareResult = await compare(password, hash)
        console.log(compareResult)
        if (compareResult) {
            const sessionId = randomstring.generate()
            res.set('Set-Cookie', `sessionId=${sessionId}; Path=/; HttpOnly`)
            // console.log(sessionId)
            res.render('succ', {
                data: JSON.stringify({
                    // message: '登录成功!'
                    username
                })
            })


        } else {
            res.render('fail', {
                data: JSON.stringify({
                    message: '密码错误'
                })
            })
        }

    } else {
        res.render('fail', {
            data: JSON.stringify({
                message: '用户名错误'
            })
        })
    }

    console.log(result)
}
//...

exports.signin = signin

登录-后端逻辑(backend)

  • 使用cookie-session第三方中间件完成验证登录

  • 安装:yarn add cookie-session -S

  • app.js


var cookieSession = require('cookie-session')
//...

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

// app.use(cors())

//设置cookie-session,注意顺序要放在最前面
app.use(cookieSession({
  name: 'session',
  keys: ['key1', 'key2']
}))

//...

routes/users.js

var express = require('express');
var router = express.Router();

const { signup, list, remove, signin, signout,isAuth } = require('../controllers/users')

const { auth } = require('../middlewares/auth')

/* GET users listing. */
router.post('/', signup);
//登录
router.post('/signin', signin)
//这里是中间件栈的知识点
router.get('/', auth, list)
router.delete('/', auth, remove)
//注销登录
router.get('/signout', auth, signout)
router.get('/isAuth', isAuth)

module.exports = router;

controllers/users.js



//用户登录
const signin = async (req, res, next) => {
    const { username, password } = req.body

    let result = await usersModel.findUser(username)

    //验证用户是否是合法用户并且密码是否正确
    if (result) {
        let { password: hash } = result
        let compareResult = await compare(password, hash)
        console.log(compareResult)
        if (compareResult) {
            req.session.username = username
            console.log(req.session)
            res.render('succ', {
                data: JSON.stringify({
                    // message: '登录成功!'
                    username
                })
            })



        } else {
            res.render('fail', {
                data: JSON.stringify({
                    message: '密码错误'
                })
            })
        }

    } else {
        res.render('fail', {
            data: JSON.stringify({
                message: '用户名错误'
            })
        })
    }

    console.log(result)
}

//退出登录
const signout = async (req, res, next) => {
    req.session = null
    res.render('succ', {
        data: JSON.stringify({
            message: '注销登录'
        })
    })
}

//验证登录
const isAuth = async (req, res, next) => {
    if (req.session.username) {
        res.render('succ', {
            data: JSON.stringify({
                // message: '验证成功'
                username: req.session.username
            })
        })
    } else {
        res.render('fail', {
            data: JSON.stringify({
                message: '验证失败,请登录'
            })
        })
    }
}
//...
exports.signout = signout
exports.isAuth = isAuth

middlewares/auth.js

const auth = (req, res, next) => {
    if (req.session.username) {
        next()
    } else {
        res.render('fail', {
            data: JSON.stringify({
                message: '请登录'
            })
        })
    }
}

exports.auth = auth

6.验证登录–frontend

app.js

//载入css
import './assets/common.css'

//载入路由
import router from './routers'
// router.go('/index')
// router.go('/')

//第一个打开的页面
$.ajax({
    url: '/api/users/isAuth',
    success(result) {
        if (result.ret) {
            console.log(result.ret)
            router.go('/index')

        } else {
            router.go('/signin')
        }

    }
})

controllers/index.js


//...

//修改登出事件绑定

const index = (router) => {
        //登出事件绑定
        $('#users-signout').on('click', (e) => {

            //默认状态下a链接有个事件会自动触发,我们要么在a链接中的href属性的值#改为javascript:void(0),要么阻止默认事件的传播:e.preventDefault()
            e.preventDefault()
            $.ajax({
                url: '/api/users/signout',
                dataType: 'json',
                success(result) {
                    if (result.ret) {
                        // router.go('/signin')
                        //直接刷新页面就行
                        location.reload()
                    } else {
                        console.log(0)
                    }
                }
            })


        })

        //初次渲染list
        _loadData()
        _list(1)


        //点击保存,提交表单
        $('#users-save').html(usersTpl())

    }
}
//提交登录表单
const _handleSubmit = (router) => {
    return (e) => {
        e.preventDefault()

        //提交表单
        const data = $('#signin').serialize()
        console.log(data)

        $.ajax({
            url: '/api/users/signin',
            type: 'post',
            dataType: 'json',
            data,
            success: function (res) {
                if (res.ret) {
                    console.log(res)
                    router.go('/index')
                }
            }
        })


    }
}
//...
//登录
const signin = (router) => {
    return (req, res, next) => {
        res.render(htmlSignin)
        $('#signin').on('submit', _handleSubmit(router))

    }
}

7.微调代码

1.backend/views/fail.ejs中ret:false

2.frontend/controllers/index.js

//...

const index = (router) => {
    const loadIndex = (res) => {
        //渲染首页
        res.render(htmlIndex)
        //window.resize(),让页面撑满整个屏幕
        $(window, '.wrapper').resize()

        //填充用户列表
        $('#content').html(usersTpl())

        //删除事件绑定
        //这里通过事件代理删除用户
        $('#users-list').on('click', '.remove', function () {
            console.log($(this).data('id'))
            $.ajax({
                url: '/api/users',
                type: 'delete',
                data: {
                    id: $(this).data('id')
                },
                success() {
                    _loadData()
                    // _pagination(dataList)
                    const isLastpage = Math.ceil(dataList.length / pageSize) === currentPage
                    const restOne = dataList.length % pageSize === 1
                    const notPageFirst = currentPage > 0
                    console.log(currentPage)
                    if (isLastpage && restOne && notPageFirst) {
                        currentPage--
                    }
                    console.log(currentPage)
                }
            })
        })
        $('#users-page').on('click', '#users-page-list li:not(:first-child , :last-child)', function () {
            const index = $(this).index()
            _list(index)
            // console.log(index)
            currentPage = index
            _setPageActive(index)
        })
        $('#users-page').on('click', '#users-page-list li:first-child ', function () {

            if (currentPage > 1) {
                currentPage--
                _list(currentPage)
                _setPageActive(currentPage)
            }

        })
        $('#users-page').on('click', '#users-page-list li:last-child ', function () {

            if (currentPage < Math.ceil(dataList.length / pageSize)) {
                currentPage++
                _list(currentPage)
                _setPageActive(currentPage)
            }

        })

        //登出事件绑定
        $('#users-signout').on('click', (e) => {

            //默认状态下a链接有个事件会自动触发,我们要么在a链接中的href属性的值#改为javascript:void(0),要么阻止默认事件的传播:e.preventDefault()
            e.preventDefault()
            $.ajax({
                url: '/api/users/signout',
                dataType: 'json',
                success(result) {
                    console.log(result)
                    if (result.ret) {

                        // router.go('/signin')
                        //直接刷新页面就行
                        location.reload()
                    } else {
                        console.log(0)
                    }
                }
            })


        })

        //初次渲染list
        _loadData()
        _list(1)


        //点击保存,提交表单
        $('#users-save').html(usersTpl())

    }
    // return async (req, res, next) => {
    return (req, res, next) => {

        $.ajax({
            url: '/api/users/isAuth',
            dataType: 'json',
            async: false,
            success(result) {
                if (result.ret) {
                    console.log(result.ret)
                    loadIndex(res)
                    router.go('/index')
                } else {
                    router.go('/signin')
                }

            }
        })


    }
}
//...

3.frontend/app.js

//载入css
import './assets/common.css'

//载入路由
import router from './routers'
// router.go('/index')
router.go('/')

//第一个打开的页面
// $.ajax({
//     url: '/api/users/isAuth',
//     success(result) {
//         if (result.ret) {
//             console.log(result.ret)
//             router.go('/index')

//         } else {
//             router.go('/signin')
//         }

//     }
// })

4.frontend/routes/index.js

import SMERouter from 'sme-router'
const router = new SMERouter('root')


import { signin, index } from '../controller'

// $('#root').html(signin)


router.route('/', signin(router))
router.route('/index', index(router))

router.route('/signin', signin(router))

// 路由守卫,所有的都要经过这里
router.use(() => {
    console.log(0)
    $.ajax({
        url: '/api/users/isAuth',
        dataType: 'json',
        success(result) {
            if (result.ret) {
                console.log(result.ret)
                router.go('/index')

            } else {
                router.go('/signin')
            }

        }
    })
})

router.route('/', () => {

})


export default router

8.分页组件的抽离

  • 模型:models

  • 我们尝试先把controller中的signin操作分离出来,其中导出的函数或者方法或者对象只有一个,我们在前端使用ES语法,export default signin,此外的方法名也是按照这个分离

frontend/controllers/signin.js

import signinTpl from '../views/signin.art'

const htmlSignin = signinTpl({})
//登录模块
const signin = (router) => {
    return (req, res, next) => {
        res.render(htmlSignin)
        $('#signin').on('submit', _handleSubmit(router))

    }
}

//提交登录表单
const _handleSubmit = (router) => {
    return (e) => {
        e.preventDefault()

        //提交表单
        const data = $('#signin').serialize()
        console.log(data)

        $.ajax({
            url: '/api/users/signin',
            type: 'post',
            dataType: 'json',
            data,
            success: function (res) {
                if (res.ret) {
                    console.log(res)
                    router.go('/index')
                } else {
                    router.go(0)
                }
            }
        })


    }
}

export default signin
  • 注意在controllers中的index.js和路由中的导入就需要进行小小的变更

我们分离组件的时候,需要注意的问题是我们怎么处理公共变量,这里我们使用事件绑定和公共类

step:

创建公共类:databus/page.js

class Page {
    constructor() {
        this.currentPage = 1
        this.pageSize = 10
    }

    setCurPage(currentPage) {
        this.currentPage = currentPage
    }

}

export default new Page()

抽离分页组件:components/pagination.js

import userListPageTpl from '../views/users-pages.art'
import page from '../databus/page'

//显示分页效果
const pagination = (data, pageSize) => {
    console.log(data.length)
    var total = data.length

    //往上取整
    const pagesCount = Math.ceil(total / pageSize)
    const pageArray = new Array(pagesCount)

    const htmlPage = userListPageTpl({
        pageArray
    })

    $('#users-page').html(htmlPage)
    //默认添加第一个
    // $('#users-page-list li:nth-child(2').addClass('active')
    // $('#users-page-list li:not(:first-child , :last-child)').on('click', function () {
    //     const index = $(this).index()
    //     $(this).addClass('active').siblings().removeClass('active')
    //     _list(index)
    //     currentPage = index
    // })

    _setPageActive(page.currentPage)

    _bindEvent(data, pageSize)


}

const _bindEvent = (data, pageSize) => {

    //分页事件绑定
    $('#users-page').on('click', '#users-page-list li:not(:first-child , :last-child)', function () {
        const index = $(this).index()
        // _list(index)
        // console.log(index)
        let currentPage = index
        // console.log('set trigger..')
        page.setCurPage(currentPage)
        $('body').trigger('changeCurPage', page.currentPage)

        _setPageActive(index)
    })


    $('#users-page').on('click', '#users-page-list li:first-child ', function () {

        if (page.currentPage > 1) {
            page.setCurPage(page.currentPage - 1)
            // page.currentPage--
            // _list(currentPage)
            $('body').trigger('changeCurPage', page.currentPage)
            _setPageActive(page.currentPage)
        }

    })
    $('#users-page').on('click', '#users-page-list li:last-child ', function () {

        if (page.currentPage < Math.ceil(data.length / pageSize)) {
            page.setCurPage(page.currentPage + 1)
            // currentPage++
            //通知外部list更新
            // _list(currentPage)
            $('body').trigger('changeCurPage', page.currentPage)
            _setPageActive(page.currentPage)
        }

    })


}


const _setPageActive = (index) => {
    // $(this).addClass('active').siblings().removeClass('active')
    $('#users-page #users-page-list li:not(:first-child , :last-child)')
        .eq(index - 1)
        .addClass('active')
        .siblings()
        .removeClass('active')
}
export default pagination

抽离之后的controllers/index.js

//es6导入模块的方法
// import router from '../routers'
import indexTpl from '../views/index.art'

import usersTpl from '../views/users.art'
import usersListTpl from '../views/users-list.art'
// import userListPageTpl from '../views/users-pages.art'
import pagination from '../components/pagination'
import page from '../databus/page'

import router from '../routers/index'


const htmlIndex = indexTpl({})

const pageSize = 5
let currentPage = 1
let dataList = []


const _loadData = () => {
    return $.ajax({
        url: '/api/users',
        async: false,
        success(result) {
            dataList = result.data
            //分页
            pagination(result.data, pageSize, currentPage)
            _list(currentPage)
        }
    })
}


//装填list数据
const _list = (pageNo) => {

    let start = (pageNo - 1) * pageSize
    $('#users-list').html(usersListTpl({
        //截取数据
        data: dataList.slice(start, start + pageSize)
    }))

}

//观察者模式
const _subscribe = () => {
    $('body').on('changeCurPage', (event, index) => {
        // console.log(index)
        console.log(page.currentPage)
        _list(index)
    })


}


//我们把绑定事件的所有操作都剥离出来成为一个方法
const _methods = () => {

    //删除事件绑定
    //这里通过事件代理删除用户
    $('#users-list').on('click', '.remove', function () {
        console.log($(this).data('id'))
        $.ajax({
            url: '/api/users',
            type: 'delete',
            data: {
                id: $(this).data('id')
            },
            success() {
                _loadData()
                // _pagination(dataList)
                const isLastpage = Math.ceil(dataList.length / pageSize) === currentPage
                const restOne = dataList.length % pageSize === 1
                const notPageFirst = page.currentPage > 0

                if (isLastpage && restOne && notPageFirst) {
                    // currentPage--
                    page.setCurPage(page.currentPage - 1)
                }

            }
        })
    })


    //登出事件绑定
    $('#users-signout').on('click', (e) => {

        //默认状态下a链接有个事件会自动触发,我们要么在a链接中的href属性的值#改为javascript:void(0),要么阻止默认事件的传播:e.preventDefault()
        e.preventDefault()
        $.ajax({
            url: '/api/users/signout',
            dataType: 'json',
            success(result) {
                console.log(result)
                if (result.ret) {

                    // router.go('/signin')
                    //直接刷新页面就行
                    location.reload()
                } else {
                    console.log(0)
                }
            }
        })


    })
    //点击保存,提交表单
    $('#users-save').html(usersTpl())
}


const index = (router) => {
    const loadIndex = (res) => {
        //渲染首页
        res.render(htmlIndex)
        //window.resize(),让页面撑满整个屏幕
        $(window, '.wrapper').resize()

        //填充用户列表
        $('#content').html(usersTpl())

        //调用事件绑定的方法,页面事件绑定
        _methods()

        //初次渲染list
        _loadData()
        _list(1)

        _subscribe()




    }
    // return async (req, res, next) => {
    return (req, res, next) => {

        $.ajax({
            url: '/api/users/isAuth',
            dataType: 'json',
            async: false,
            success(result) {
                if (result.ret) {
                    console.log(result.ret)
                    loadIndex(res)
                    router.go('/index')
                } else {
                    router.go('/signin')
                }

            }
        })


    }
}



//添加用户
const _signup = () => {
    const $btnClose = $('#users-close')

    //提交表单
    const data = $('#users-form').serialize()
    console.log(data)

    $.ajax({
        url: '/api/users',
        type: 'post',
        data,
        success: async (res) => {
            console.log(res)
            //提交数据后渲染
            //刷新页面
            page.setCurPage(1)
            _loadData()
            _list(1)
        }
    })
    //单击关闭模拟框
    $btnClose.click()

}

const signup = () => {

}



export default index

9.用户登录–token方案

后端


const fs = require('fs')
const path = require('path')
const jwt = require('jsonwebtoken')

//私钥用来加密
const privateKey = fs.readFileSync(path.join(__dirname, '../keys/rsa_private_key.pem'))
//公钥用来验证
const publicKey = fs.readFileSync(path.join(__dirname, '../keys/rsa_public_key.pem'))


//生成token,加密
exports.sign = (username) => {

    const token = jwt.sign({ username }, privateKey, { algorithm: 'RS256' })
    return token

}
//验证
exports.verify = (token) => {
    const result = jwt.verify(token, publicKey)
    return result
}

  • 修改验证逻辑,我们把token种到请求头里:controllers/users.js

//用户登录
const signin = async (req, res, next) => {
  	//...
    //验证用户是否是合法用户并且密码是否正确
    if (result) {

        console.log(compareResult)
        if (compareResult) {

            // req.session.username = username
            //生成token
            const token = sign(username)
            // console.log(token)
            //自定义守护字段一般以大写的X开头,注意规范
            res.set('X-Access-Token', token)

            res.render('succ', {
                data: JSON.stringify({
                    // message: '登录成功!'
                    username
                })
            })

		//...
}

  • 测试:通过insmoina发送登录请求

前端

controllers/signin.js

//提交登录表单
const _handleSubmit = (router) => {
    return (e) => {
        e.preventDefault()

        //提交表单
        const data = $('#signin').serialize()
        console.log(data)

        $.ajax({
            url: '/api/users/signin',
            type: 'post',
            dataType: 'json',
            data,
            success: function (res, textStatus, jqXHR) {
                const token = jqXHR.getResponserHeader('X-Access-Token')
                // console.log(responseHeader)
                localStorage.setItem('lg-token', token)
                // if (res.ret) {
                //     console.log(res)
                //     router.go('/index')
                // } else {
                //     router.go(0)
                // }
            }
        })


    }
}

routes/index.js

// 路由守卫,所有的都要经过这里
router.use(() => {
    // console.log(0)
    $.ajax({
        url: '/api/users/isAuth',
        dataType: 'json',
        headers: {
            'X-Access-Token': localStorage.getItem('lg-token')
        },
        success(result) {
            if (result.ret) {
                console.log(result.ret)
                router.go('/index')

            } else {
                router.go('/signin')
            }

        }
    })
})

  • 不得不说这个老师讲课逻辑太乱了
  • 后端:

controllers/users.js


//验证登录
const isAuth = async (req, res, next) => {

    let token = req.get('X-Access-Token')

    try {
        let result = verify(token)
        console.log(result)
        res.render('succ', {
            data: JSON.stringify({
                // message: '验证成功'
                username: result.username
            })
        })
    } catch (e) {
        res.render('fail', {
            data: JSON.stringify({
                message: '验证失败,请登录'
            })
        })
    }
    // }
    // if (req.session.username) {
    //     res.render('succ', {
    //         data: JSON.stringify({
    //             // message: '验证成功'
    //             username: req.session.username
    //         })
    //     })
    // } else {
    //     res.render('fail', {
    //         data: JSON.stringify({
    //             message: '验证失败,请登录'
    //         })
    //     })
    // }
}

middlewares/auth.js

const auth = (req, res, next) => {
    // if (req.session.username) {
    //     next()
    // } else {
    //     res.render('fail', {
    //         data: JSON.stringify({
    //             message: '请登录'
    //         })
    //     })
    // }

    let token = req.get('X-Access-Token')

    try {
        let result = verify(token)
        console.log(result)
        next()

    } catch (e) {
        res.render('fail', {
            data: JSON.stringify({
                message: '验证失败,请登录'
            })
        })
    }
}

exports.auth = auth
  • 在前端的所有ajax请求中都需要加上请求头,使用ctrl+F所有ajax然后逐个添加:
$.ajax({
        url: '/api/users',
        type: 'post',
        data,
        headers: {
          'X-Access-Token':localStorage.getItem('token')  
        },
        success: async (res) => {
          //...
        }
    })
  • 在登出时记得把token删除

10.Model层的抽离

//…

  • 如果返回的是Promice对象需要使用同步关键字

  • import {modelname as yourname} from modelpath

  • 通用的组件应该抽离出来变成工具

11.路由改造

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值