共计 6931 个字符,预计需要花费 18 分钟才能阅读完成。
(二)我的项目性能的实现——用户治理
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');
// 导入 bcrypt
const 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-gyp
npm 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
// 导入 bcrypt
const 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}}
正文完