自定义nodeJs脚手架相关配置
分类: Nodejs 311 0
代码地址:https://github.com/zjiafeng/userinfo/tree/master/nodeJs/16server
1、引入所需模块(模块版本默认最新) cnpm isntall
"art-template": "^4.13.2",
"jsonwebtoken": "^8.5.1",
"koa": "^2.12.0",
"koa-art-template": "^1.1.1",
"koa-bodyparser": "^4.3.0",
"koa-generic-session": "^2.0.4",
"koa-redis": "^4.0.1",
"koa-router": "^9.0.1",
"koa-static": "^5.0.0",
"md5": "^2.2.1",
"mongodb": "^3.5.9",
"nodemailer": "^6.4.8",
"svg-captcha": "^1.4.0"
2、新建入口文件 配置各个模块
/**引入所需模块 */
const Koa = require('koa'),
Router = require('koa-router'),
render = require('koa-art-template'),
path = require('path'),
svgCaptcha = require('svg-captcha'),
session = require('koa-generic-session'),
Redis = require('koa-redis'),
bodyParser = require('koa-bodyparser'),
serve = require('koa-static');
/**实例化 */
const app = new Koa();
const router = new Router();
// 配置koa-art-template 模板引擎
render(app, {
root: path.join(__dirname, 'views'), // 模板引擎位置
extname: '.html', // 文件后缀名
debug: process.env.NODE_ENV !== 'production' //是否开启调试模式
});
//引入子模块
var api=require('./routes/api.js');
var index=require('./routes/index.js');
//配置路由
router.use('/api',api); /*在模块里面暴露路由并且启动路由*/
router.use(index);
// 路由中间件 (拦截)
app.use(async (ctx, next) => {
await next();
if (ctx.status == 404) {
ctx.body = '404. 抱歉,您访问的资源不存在'
} else {
// console.log(ctx.url)
}
})
app.use(bodyParser()); // 必须放到启动路由前调用
app.use(serve(__dirname + '/public')); //启动koa-static
// 一些session和redis相关配置
app.keys = ['keys', 'keykeys'];
app.use(session({
store: new Redis()
}));
app.use(router.routes()).use(router.allowedMethods()); //启动路由 必须放在其他模块后
app.listen(3000);
3、新建公共文件目录 util/conf.js
/**mongodb数据库配置文件 */
// 定义连接数据库的地址 集合名称
const app = {
dbUrl: 'mongodb://localhost:27017/',
dbName: 'server01',
smtp: {
get host() {
return 'smtp.qq.com'
},
get user() {
return '2621275142@qq.com' // qq邮箱名
},
get pass() {
return 'jkhrgzgopqkbdibe' // qq邮箱授权码
},
// 邮箱验证码
get code() {
return () => {
return Math.random()
.toString(16)
.slice(2, 6)
.toUpperCase()
}
},
// 定义验证码过期时间rules,5分钟内邮箱
get expire() {
return () => {
return new Date().getTime() + 5 * 60 * 1000
}
}
},
redis: {
get host() {
return '127.0.0.1'
},
get port() {
return 6379
}
}
}
module.exports = app;
4、新建公共文件目录 util/db.js 对数据操作进行封装
const MongoClient = require('mongodb').MongoClient; //引入mongodb数据库模块
const ObjectID = require('mongodb').ObjectID;
var Config = require('./conf'); //引入配置文件
const client = new MongoClient(Config.dbUrl, { useNewUrlParser: true, useUnifiedTopology: true });
class Db {
static getInstance() { /*1、单例 多次实例化实例不共享的问题*/
if (!Db.instance) {
Db.instance = new Db();
}
return Db.instance;
}
constructor() {
this.dbClient = ''; /*属性 放db对象*/
this.connect();
}
connect() { //连接数据库
let _that = this;
return new Promise((resolve, reject) => {
if (!_that.dbClient) { /**解决数据库多次连接问题 */
client.connect((err, client) => {
if (err) {
reject(err)
} else {
_that.dbClient = client.db(Config.dbName);
resolve(_that.dbClient)
}
})
} else {
resolve(_that.dbClient)
}
})
}
find(collectionName, json) {
return new Promise((resolve, reject) => {
this.connect().then((db) => {
var result = db.collection(collectionName).find(json);
result.toArray(function (err, docs) {
if (err) {
reject(err);
return;
}
resolve(docs);
})
})
})
}
updata(collectionName, jsonOld, jsonNew) {
return new Promise((resolve, reject) => {
this.connect().then((db) => {
db.collection(collectionName).updateMany(jsonOld, {$set:jsonNew}, (err, docs) => {
if (err) {
reject(err);
return
}
resolve(docs);
})
})
})
}
insert(collectionName, json) {
return new Promise((resolve, reject) => {
this.connect().then((db) => {
db.collection(collectionName).insertOne(json, (err, docs) => {
if (err) {
reject(err);
return
}
resolve(docs)
})
})
})
}
remove(collectionName, json) {
return new Promise((resolve, reject) => {
this.connect().then((db) => {
db.collection(collectionName).removeOne(json, (err, docs) => {
if (err) {
reject(err);
return
}
resolve(docs)
})
})
})
}
getObjectId(id) { //mongodb中查询_id把字符串转换为对象
return new ObjectID(id);
}
}
module.exports = Db.getInstance();
5、新建公共文件目录 util/tool.js
var md5 = require('md5'), jwt = require('jsonwebtoken');
let tools = {
md5(str) {
return md5(str);
},
createToken(user_id) {
const token = jwt.sign(
{
user_id: user_id
},
'zhangjf',
{
expiresIn: '1h'
}
)
return token
}
}
module.exports = tools;
6、新建公共文件目录 util/checkToken.js jwt验证token
const jwt = require('jsonwebtoken');
//检查token是否过期
module.exports = async ( ctx, next ) => {
//拿到token
const authorization = ctx.get('Authorization');
if (authorization === '') {
ctx.throw(401, 'no token detected in http headerAuthorization');
}
const token = authorization.split(' ')[1];
let tokenContent;
try {
tokenContent = await jwt.verify(token, 'zhangjf');//如果token过期或验证失败,将抛出错误
} catch (err) {
ctx.throw(401, 'invalid token');
}
await next();
};
7、登录接口模块的具体操作
var router = require('koa-router')();
var tools = require('../../util/tool.js');
var Db = require('../../util/db.js');
var nodeMailer = require('nodeMailer');
var Config = require('../../util/conf'); //引入配置文件
var Redis = require('koa-redis');
var checkToken = require('../../util/checkToken');
// 获取redis的客户端
const Store = new Redis().client
// 发送验证码
router.post('/verify', async (ctx, next) => {
const username = ctx.request.body.username;
const saveExpire = await Store.hget(`nodemail:${username}`, 'expire') // 拿到过期时间
console.log(ctx.request.body)
console.log('当前时间:', new Date().getTime())
console.log('过期时间:', saveExpire)
// 检验已存在的验证码是否过期,以限制用户频繁发送验证码
if (saveExpire && new Date().getTime() - saveExpire < 0) {
ctx.body = {
code: -1,
msg: '发送过于频繁,请稍后再试'
}
return
}
// QQ邮箱smtp服务权限校验
const transporter = nodeMailer.createTransport({
/**
* 端口465和587用于电子邮件客户端到电子邮件服务器通信 - 发送电子邮件。
* 端口465用于smtps SSL加密在任何SMTP级别通信之前自动启动。
* 端口587用于msa
*/
host: Config.smtp.host,
port: 587,
secure: false, // 为true时监听465端口,为false时监听其他端口
auth: {
user: Config.smtp.user,
pass: Config.smtp.pass
}
})
// 邮箱需要接收的信息
const ko = {
code: Config.smtp.code(),
expire: Config.smtp.expire(),
email: ctx.request.body.email,
username: ctx.request.body.username
}
// 邮件中需要显示的内容
const mailOptions = {
from: `"认证邮件" <${Config.smtp.user}>`, // 邮件来自
to: ko.email, // 邮件发往
subject: '邀请码', // 邮件主题 标题
html: `用户${ko.username},您正在注册****,您的邀请码是${ko.code}` // 邮件内容
}
// 执行发送邮件
await transporter.sendMail(mailOptions, (err, info) => {
if (err) {
return console.log('发送邮件失败')
} else {
console.log(`nodemail:${ko.username}`, 'code', ko.code, 'expire', ko.expire, 'email', ko.email);
Store.hmset(`nodemail:${ko.username}`, 'code', ko.code, 'expire', ko.expire, 'email', ko.email)
}
})
ctx.body = {
code: 0,
msg: '验证码已发送,请注意查收,可能会有延时,有效期5分钟'
}
})
// 注册接口
router.post('/register', async (ctx) => {
let { username, password, email, code } = ctx.request.body
console.log(ctx.request.body);
if (code) {
const saveCode = await Store.hget(`nodemail:${username}`, 'code') // 拿到已存储的真实的验证码
const saveExpire = await Store.hget(`nodemail:${username}`, 'expire') // 过期时间
console.log(ctx.request.body)
console.log('redis中保存的验证码:', saveCode)
console.log('当前时间:', new Date().getTime())
console.log('过期时间:', saveExpire)
// 用户提交的验证码是否等于已存的验证码
if (code === saveCode) {
if (new Date().getTime() - saveExpire > 0) {
ctx.body = {
code: -1,
msg: '验证码已过期,请重新申请'
}
return
}
} else {
ctx.body = {
code: -1,
msg: '请填写正确的验证码'
}
return
}
} else {
ctx.body = {
code: -1,
msg: '请填写验证码'
}
return
}
// 用户名是否已经被注册
const user = await Db.find('userlist', {"username":username})
if (user.length) {
ctx.body = {
code: -1,
msg: '该用户名已被注册'
}
return
}
// 如果用户名未被注册,则写入数据库
const newUser = await Db.insert('userlist',{
username,
password,
email,
token: tools.createToken(this.username) // 生成一个token 存入数据库
})
// console.log(newUser);
// 如果用户名被成功写入数据库,则返回注册成功
if (newUser.ok = 1) {
ctx.body = {
code: 0,
msg: '注册成功',
}
} else {
ctx.body = {
code: -1,
msg: '注册失败'
}
}
})
// 登录接口
router.post('/login',async (ctx)=>{
let {username, password} = ctx.request.body;
result = await Db.find('userlist',{username});
console.log(result);
if(!result){
ctx.body = {
code: -1,
msg: '用户名不存在'
}
}else if(result[0].password != password){
ctx.body = {
code: -1,
msg: '用户密码错误'
}
}else if(result[0].password == password){
let token = tools.createToken(username)
// console.log(token)
try {
await Db.updata('userlist',{username:username},{token:token});
ctx.body = {
code: 0,
msg: '登录成功',
data: [
{username,token}
]
}
} catch (error) {
ctx.body = {
code: -1,
msg: '登录失败,请重新登录'
}
}
}
})
// 获取所有用户列表
router.get('/getAlluser',checkToken, async (ctx)=>{
ctx.body = '用户查找'
try {
let newArr = [];
let result = await Db.find('userlist',{});
result.map((value,index)=>{
newArr.push({
username: value.username,
email: value.email
})
})
console.log(result);
ctx.body = {
code: 0,
msg: '用户查询成功',
data: [{newArr}]
}
} catch (error) {
ctx.body = {
code: -1,
msg: '查找失败',
result: err
}
}
})
module.exports = router.routes();
共 0 条评论关于 “自定义nodeJs脚手架相关配置”