(二)我的项目性能的实现——用户治理
BLOG -- 源码目录 └── middleware 中间件 └──loginGuard.js 登录拦挡 └── model -- 数据库操作 ├── connect.js --数据库连贯 └── user.js --用户治理 └── public -- 动态资源 └── admin --博客治理页面动态资源 └── common.js --客户端验证登录表单└── route -- 路由 └── admin --博客治理页面 ├──loginPage.js 登录页面渲染 ├──logout.js 退出页面性能实现 ├──userPage.js 用户页面渲染 └── login.js 登录页面性能实现 └── admin.js --博客治理页面路由 └── views -- 模板 └── admin --博客治理页面art模板 └── common 公共模块 └── header.art 公共头部模块 ├── login.art --登录页面 └── error.art --谬误页面 ├── app.js -- 创立网站服务 └──hash.js -- 对bcrypt的测试代码
1、connect.js
- 链接数据库: 引入mongoose、链接数据库
// 引入mongoose第三方模块const mongoose = require('mongoose');// 导入config模块const config = require('config');console.log(config.get('db.host'))// 连贯数据库mongoose.connect(`mongodb://${config.get('db.user')}:${config.get('db.pwd')}@${config.get('db.host')}:${config.get('db.port')}/${config.get('db.name')}`, {useNewUrlParser: true }) .then(() => console.log('数据库连贯胜利')) .catch(() => console.log('数据库连贯失败'))
2.app.js
- 数据库链接:require connect
require('./model/user');·// 创立用户,建完之后须要正文掉服务器端接管申请参数,验证用户是否填写了登录表单:
- 下载好第三方模块后重新启动服务器
npm install body-parser
- app.js 引入body-parser模块 用来解决post申请参数
- 下载好第三方模块后重新启动服务器
- 显示登录状态,须要保留登录的状态:导入express-session模块,
npm install express-session
拦挡申请 判断用户登录状态, - 拦挡申请 判断用户登录状态,require loginGuard
// 援用expess框架const express = require('express');// 解决门路const path = require('path');// 引入body-parser模块 用来解决post申请参数const bodyPaser = require('body-parser');// 导入express-session模块const session = require('express-session');// 创立网站服务器const app = express();// 数据库连贯require('./model/connect');// 解决post申请参数app.use(bodyPaser.urlencoded({extended: false}));// 通知express框架模板所在的地位app.set('views', path.join(__dirname, 'views'));// 通知express框架模板的默认后缀是什么app.set('view engine', 'art');// 当渲染后缀为art的模板时 所应用的模板引擎是什么app.engine('art', require('express-art-template'));// 凋谢动态资源文件app.use(express.static(path.join(__dirname, 'public')));// 引入路由模块const home = require('./route/home');const admin = require('./route/admin');// 拦挡申请 判断用户登录状态app.use('/admin', require('./middleware/loginGuard'));// 为路由匹配申请门路app.use('/home', home);app.use('/admin', admin);// 监听端口app.listen(80);console.log('网站服务器启动胜利, 请拜访localhost')
3.user.js
- 创立用户汇合,初始化用户:
汇合创立后记得删除,否则会反复创立报错,将用户汇合做为模块成员进行导出 - 应用了bcrypt加密形式,导入bcrypt模块,
// 创立用户汇合// 引入mongoose第三方模块const mongoose = require('mongoose');// 导入bcryptconst bcrypt = require('bcrypt');// 创立用户汇合规定const userSchema = new mongoose.Schema({ username: { ··· }, email: { ··· }···});// 创立汇合async function createUser () { const salt = await bcrypt.genSalt(10); const pass = await bcrypt.hash('123456', salt); const user = await User.create({ username: 'xx', email: 'xx', password: pass, role: 'admin', state: 0 });}// createUser();// 将用户汇合做为模块成员进行导出module.exports = { User}
4.login.art
- 为登录表单项设置申请地址、申请形式以及表单项name属性,为不便获取表单,为表单增加id值
- 如果邮件和明码其中一项没有输出,阻止表单提交
<body><div class="login"> <form action="xx" method="post" id="loginForm">··· <input name="email" type="email" class="xx" placeholder="请输出邮件地址">···<script type="text/javascript"> // 为表单增加提交事件 $('#loginForm').on('submit', function () { // 获取到表单中用户输出的内容 var result = serializeToJson($(this)) // 如果用户没有输出邮件地址的话 if (result.email.trim().length == 0) { alert('请输出邮件地址'); // 阻止程序向下执行 return false; } // 如果用户没有输出明码 if (result.password.trim().length == 0) { alert('请输出明码') // 阻止程序向下执行 return false; } }); </script></body>
5.common.js
- 当用户点击登录按钮时,客户端验证用户是否填写了登录表单,并增加到layout.js中,使得每个页面都能够拜访到
function serializeToJson(form) { var result = {}; // [{name: 'email', value: '用户输出的内容'}] var f = form.serializeArray(); f.forEach(function (item) { // result.email result[item.name] = item.value; }); return result;}
layout.js
<!DOCTYPE html><html lang="en"><head> ··· {{block 'link'}}{{/block}}</head><body> {{block 'main'}} {{/block}} ··· <script src="/admin/js/common.js"></script> {{block 'script'}} {{/block}}</body></html>
6.login.js
- 实现登录性能,如果其中一项没有输出(trim().length == 0),为客户端做出响应,阻止程序向下执行
- 依据邮箱地址查问用户信息(导入用户汇合构造函数),如果用户不存在(用findOne查问),为客户端做出响应,阻止程序向下执行
如果用户存在,将用户名和明码(应用了bcrypt加密)进行比对(bcrypt.compare(password, user.password)),比对胜利,用户登录胜利,比对失败,用户登录失败
- 明码加密解决 bcrypt
bcrypt依赖的其余环境
1.装置python 并把python设置到环境变量中
2.node-gypnpm install node-gyp -g
3.windows-build-toolsPython 2版本:
npm install --global --production windows-build-tools
Python其它版本:https://blog.csdn.net/weixin_...- 对用户角色进行判断, 将用户角色存储在session对象中,如果不是admin至登录页面,如果是则进入用户列表页面
- req.app.locals,req能够取得app对象,抉择其中的locals属性,能够不必屡次渲染
- render('admin/error')跳转失败则渲染error页面
// 导入用户汇合构造函数const { User } = require('../../model/user');const bcrypt = require('bcrypt');module.exports = async (req, res) => { // 接管申请参数 const {email, password} = req.body; // 如果用户没有输出邮件地址 // if (email.trim().length == 0 || password.trim().length == 0) return res.status(400).send('<h4>邮件地址或者明码谬误</h4>'); if (email.trim().length == 0 || password.trim().length == 0) return res.status(400).render('admin/error', {msg: '邮件地址或者明码谬误'}); // 依据邮箱地址查问用户信息 // 如果查问到了用户 user变量的值是对象类型 对象中存储的是用户信息 // 如果没有查问到用户 user变量为空 let user = await User.findOne({email}); // 查问到了用户 if (user) { // 将客户端传递过去的明码和用户信息中的明码进行比对 // true 比对胜利 // false 比照失败 let isValid = await bcrypt.compare(password, user.password); // 如果明码比对胜利 if ( isValid ) { // 登录胜利 // 将用户名存储在申请对象中 req.session.username = user.username; // 将用户角色存储在session对象中 req.session.role = user.role; // res.send('登录胜利'); req.app.locals.userInfo = user; // 对用户的角色进行判断 if (user.role == 'admin') { // 重定向到用户列表页面 res.redirect('/admin/user'); } else { // 重定向到博客首页 res.redirect('/home/'); } } else { // 没有查问到用户 res.status(400).render('admin/error', {msg: '邮箱地址或者明码谬误'}) } } else { // 没有查问到用户 res.status(400).render('admin/error', {msg: '邮箱地址或者明码谬误'}) }}
7.header.art
- {{userInfo && userInfo.username}}判断userInfo是否存在,避免因为不存在而呈现的报错
<!-- 头部 --><div class="header"> <!-- 用户信息 --> <div class="info"> <div class="profile dropdown fr"> <span class="btn dropdown-toggle" data-toggle="dropdown"> {{userInfo && userInfo.username}} <span class="caret"></span> </span> </div> </div> <!-- /用户信息 --></div>
8.loginGuard.js
- 实现登录拦挡的性能:判断除了login以外的页面且曾经属于登录状态(req.url != '/login' && !req.session.username)再判断用户属性是普通用户还是管理员
onst guard = (req, res, next) => { // 判断用户拜访的是否是登录页面 // 判断用户的登录状态 // 如果用户是登录的 将申请放行 // 如果用户不是登录的 将申请重定向到登录页面 if (req.url != '/login' && !req.session.username) { res.redirect('/admin/login'); } else { // 如果用户是登录状态 并且是一个普通用户 if (req.session.role == 'normal') { // 让它跳转到博客首页 阻止程序向下执行 return res.redirect('/home/') } // 用户是登录状态 将申请放行 next(); }}module.exports = guard;
9.hash.js
// 导入bcryptconst bcrypt = require('bcrypt');async function run () { // 生成随机字符串 // genSalt办法接管一个数值作为参数 // 数值越大 生成的随机字符串复杂度越高 // 数值越小 生成的随机字符串复杂度越低 // 默认值是 10 // 返回生成的随机字符串 const salt = await bcrypt.genSalt(10); // 对明码进行加密 // 1. 要进行加密的明文 // 2. 随机字符串 // 返回值是加密后的明码 const result = await bcrypt.hash('123456', salt); console.log(salt); console.log(result);}run();
10.loginPage.js
- 模块拆散性能:实现登录页面的渲染
- 通过模块化来实现代码的复用,最初要把路由对象作为模块成员进行导出
- 相似的还有logout.js userPage.js login.js
module.exports = (req, res) => { res.render('admin/login');}
11.admin.js
- 通过require把到处去的模块成员接入
- admin同样作为模块成员进行导出,让app.js接入
// 援用expess框架const express = require('express');// 创立博客展现页面路由const admin = express.Router();// 渲染登录页面admin.get('/login', require('./admin/loginPage'));// 实现登录性能admin.post('/login', require('./admin/login'));// 创立用户列表路由admin.get('/user', require('./admin/userPage'));// 实现退出性能admin.get('/logout', require('./admin/logout'));// 将路由对象做为模块成员进行导出module.exports = admin;
12、error.art
- 优化页面:谬误页面三秒后返回登录页面,基于layout骨架
{{extend './common/layout.art'}}{{block 'main'}} <p class="bg-danger error">{{msg}}</p>{{/block}}{{block 'script'}} <script type="text/javascript"> setTimeout(function () { location.href = '/admin/login'; }, 3000) </script>{{/block}}