基于Egg.js二次封装框架,一键安装,干货上场

安装

js 复制代码
npm i egg-bag-framework

内置多种模块,中间件以及工具

源码地址, 演示地址

中间件

校验sing签名是否合法,防止随意发起请求

js 复制代码
'use strict';
module.exports = (option, app) => {
    return async function sing(ctx, next) {
        const sing = ctx.request.header.sing;
        const { domain, expireTime, cache } = ctx.app.config.website;
        const default_cache = 'redis';
        if (sing) {
            let getSing = null;
            if (cache === default_cache) {
                getSing = await app.redis.get(sing);
            } else {
                getSing = await app.lru.get(sing);
            }
            if (getSing) {
                ctx.body = ctx.resultData({ msg: 'sing签名已过期' }); // 在存在说明既过期
            } else {
                try {
                    const decSing = ctx.helper.aesDecrypt(sing);
                    const singData = JSON.parse(decSing);
                    if (singData.domain === domain) {
                        if (cache === default_cache) {
                            await app.redis.set(sing, 1);
                        } else {
                            await app.lru.set(sing, 1);
                        }
                        await app.redis.set(sing, 1);
                        await app.redis.expire(sing, expireTime);
                        await next();
                    } else {
                        ctx.body = ctx.resultData({ msg: 'sing签名不合法,缺少字符串' });
                    }
                } catch (e) {
                    ctx.body = ctx.resultData({ msg: 'sing签名不合法' });
                }
            }
        } else {
            ctx.body = ctx.resultData({ msg: '缺少sing签名' });
        }
    };
};

限流中间件

防止接口被恶意盗刷,如果被攻击了,请求使用nginx或者服务器配置白黑名单

js 复制代码
'use strict';
const { RateLimiterMemory } = require('rate-limiter-flexible'); // 限流中间件
module.exports = () => {
    // 创建一个基于内存的令牌桶速率限制器,每秒限制 12 次请求
    const opts = {
        points: 12,
        duration: 1,
    };
    const rateLimiter = new RateLimiterMemory(opts);
    return async function limiter(ctx, next) {
        rateLimiter.consume(ctx.request.ip)
            .then(rateLimiterRes => {
                next();
            })
            .catch(rateLimiterRes => {
                ctx.body = ctx.resultData({ msg: '触发限流了', code: 2001 });
            });
    };
};

验证jwt

js 复制代码
'use strict';

module.exports = () => {
    return async function authority(ctx, next) {
        const authorization = ctx.request.header.authorization;
        if (authorization) {
            try {
                ctx.helper.verifyToken(authorization); // 验证jwt
                await next();
            } catch (err) {
                ctx.body = ctx.resultData({ msg: 'access_token过期', code: 1003 });
            }
        } else {
            ctx.body = ctx.resultData({ msg: '缺少access_token', code: 1003 });
        }
    };
};

内置模块

jwt

(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的

js 复制代码
// plugin.js
exports.jwt = {  
    enable: true,  
    package: 'egg-jwt',  
};
js 复制代码
// config.default.js
config.jwt = {  
    secret: 'ABCD20231017QWERYSUNXSJL', // 可以自定义  
    sign: {  
        expiresIn: 8 * 60 * 60, // 过期时间8小时  
    },  
};

Validate

参数校验模块

js 复制代码
// plugin.js
exports.validate = {  
    enable: true,  
    package: 'egg-validate',  
};
js 复制代码
// config.default.js
config.validate = {  
    convert: true,  
    translate() {  
        const args = Array.prototype.slice.call(arguments);  
        return I18n.__.apply(I18n, args);  
    },  
};

redis

Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理

js 复制代码
// plugin.js
exports.redis = {  
    enable: true,  
    package: 'egg-redis',  
};
js 复制代码
// config.default.js
config.redis = {  
    client: {  
        port: 6379,  
        host: '127.0.0.1',  
        password: 'auth',  
        db: 0,  
    },  
}

lru

本地缓存

js 复制代码
exports.lru = {  
    enable: true,  
    package: 'egg-lru', // 本地缓存  
};
js 复制代码
config.lru = {  
    client: {  
        max: 3000, // 所有lru缓存配置可用  
        maxAge: 1000 * 60 * 30, // 60 min cache  
    },  
    app: true, // 加载到app中,默认是打开的  
    agent: false, // 加载到代理中,默认为关闭  
};

上传模式

js 复制代码
// config.default.js
config.multipart = {  
    mode: 'file',  
    fileSize: '50mb', // 接收文件大小  
    whitelist: [ // 允许接收的文件类型  
        '.png',  
        '.jpg',  
        '.webp',  
        '.gif',  
        '.zip',  
        '.doc',  
        '.docx',  
        '.txt',  
        '.xlsx',  
        '.pdf',  
        '.mp4',  
        '.webm',  
        '.mov',  
        '.flv',  
        '.avi',  
        '.f4v',  
        '.mov',  
        '.m4v',  
        '.rmvb',  
        '.rm',  
        '.mpg',  
        '.mpeg',  
    ],  
};

Sequelize

Sequelize 是一个基于 promise 的 Node.js ORM, 目前支持 Postgres, MySQL, MariaDB, SQLite 以及 Microsoft SQL Server. 它具有强大的事务支持, 关联关系, 预读和延迟加载,读取复制等功能

js 复制代码
// plugin.js
exports.sequelize = {  
    enable: true,  
    package: 'egg-sequelize',  
};
js 复制代码
config.sequelize = {  
    dialect: 'mysql',  
    database: 'pm_webleading',  
    host: '127.0.0.1',  
    port: '3306',  
    username: 'pm_webleading',  
    password: '123456',  
    underscored: false,  
    timezone: '+08:00',  
    define: {  
        timestamps: true,  
        freezeTableName: true,  
    },  
};

Mysql

MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用软件之一

js 复制代码
// plugin.js
exports.mysql = {  
    enable: true,  
    package: 'egg-mysql',  
};
js 复制代码
// config.default.js
config.mysql = {  
    client: {  
    // host  
    host: '127.0.0.1',  
    // 端口号  
    port: '3306',  
    // 用户名  
    user: 'pm_webleading',  
    // 密码  
    password: '123456',  
    // 数据库名  
    database: 'pm_webleading',  
    },  
    // 是否加载到 app 上,默认开启  
    app: true,  
    // 是否加载到 agent 上,默认关闭  
    agent: false,  
};

内置工具

已挂在egg.js,ctx对象上调用方法如下

js 复制代码
'use strict';  
  
const {Controller} = require('egg');  
  
class HomeController extends Controller {  
    async index() {  
       const {ctx} = this;  
        try {  
            for (const file of ctx.request.files) {  
               const filePath = await ctx.helper.uploadLocaFile({file})  // cxt.helper.xxxx
            }  
        } finally {  
           await ctx.cleanupRequestFiles();  
        }  
    }
}
module.exports = HomeController;

上传文件本地

可以上传以上配置类型的文件

js 复制代码
uploadLocaFile({ file, filePath }) {  
    const { ctx } = this;  
    return new Promise(async (resolve, reject) => {  
        try {  
            const filename = file.filename;  
            const extname = path.extname(filename);  
            const _filePath = filePath || `public/upload/${ctx.helper.nanoid()}${extname}`;  
            const localPath = path.join(ctx.app.baseDir, 'app', _filePath);  
            // 读取文件  
            const source = fs.createReadStream(file.filepath);  
            // 创建写入流  
            const target = fs.createWriteStream(localPath);  
            await pump(source, target);  
            resolve(_filePath);  
        } catch (err) {  
            reject(err);  
        }  
    });  
}

上传图片-带压缩

只能上传图片

js 复制代码
uploadLocalImage({ file, filePath, width = 500, quality = 75 }) {
        const { ctx } = this;
        const extname = path.extname(file.filename);
        const _filePath = filePath || `public/image/${ctx.helper.nanoid()}${extname}`;
        const localPath = path.join(ctx.app.baseDir, 'app', _filePath);
        return new Promise((resolve, reject) => {
            Jimp.read(file.filepath)
                .then(image => {
                    image.resize(width, Jimp.AUTO)
                        .quality(quality)
                        .write(localPath);
                    resolve(_filePath);
                })
                .catch(err => {
                    reject(err);
                });
        });
    }

对称加密

js 复制代码
aesEncrypt(data, options) {
        options = Object.assign({ key: this.app.config.website.key, iv: this.app.config.website.iv }, options);
        let str = data;
        if (typeof data === 'object') {
            str = JSON.stringify(data);
        }
        str = CryptoJS.enc.Utf8.parse(str);
        const crypto = CryptoJS.AES.encrypt(str, CryptoJS.enc.Utf8.parse(options.key), {
            iv: CryptoJS.enc.Utf8.parse(options.iv),
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7,
        });
        return crypto.toString(); // 对称加密内容
    },

对称解密

js 复制代码
aesDecrypt(data, options) {
        options = Object.assign({ key: this.app.config.website.key, iv: this.app.config.website.iv }, options);
        const decrypt = CryptoJS.AES.decrypt(data, CryptoJS.enc.Utf8.parse(options.key), {
            iv: CryptoJS.enc.Utf8.parse(options.iv),
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7,
        });
        return CryptoJS.enc.Utf8.stringify(decrypt); // 对称解密内容
    },

非对称加密

js 复制代码
 encrypt(str, options) {
        options = Object.assign({ publicKey: this.app.config.website.publicKey }, options);
        const encrypted = new JSEncrypt();
        encrypted.setPublicKey(options.publicKey.toString());
        return encrypted.encrypt(str); // 非对称加密字符串
    },

非对称解密

js 复制代码
decrypt(str, options) {
        options = Object.assign({ privateKey: this.app.config.website.privateKey }, options);
        const decrypted = new JSEncrypt(); // 创建解密对象实例
        decrypted.setPrivateKey(options.privateKey.toString()); // 设置私钥
        return decrypted.decrypt(str); // 非对称解密内容
    },

md5加密

js 复制代码
md5(data) {
        let str = data;
        if (typeof data === 'object') {
            str = JSON.stringify(data);
        }
        return CryptoJS.MD5(str)
            .toString();
    },

随机ID

js 复制代码
nanoid(size = 12) {
        const nanoid = customAlphabet(alphabet.join(''), size);
        if (size >= 12) {
            return dayjs()
                .format('YYYYMMDD') + nanoid(); // 获取不重复随机ID
        }
        return nanoid(); // 获取重复随机ID

    },

jwt-生成token-校验token

js 复制代码
generateToken(data) {
        return this.app.jwt.sign(data, this.app.config.jwt.secret); // 生成token
    },
    verifyToken(token) {
        return this.app.jwt.verify(token, this.app.config.jwt.secret); // 验证token
    },
相关推荐
前端小小王34 分钟前
React Hooks
前端·javascript·react.js
迷途小码农零零发44 分钟前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
娃哈哈哈哈呀1 小时前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
旭东怪2 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
ekskef_sef3 小时前
32岁前端干了8年,是继续做前端开发,还是转其它工作
前端
sunshine6414 小时前
【CSS】实现tag选中对钩样式
前端·css·css3
真滴book理喻4 小时前
Vue(四)
前端·javascript·vue.js
蜜獾云4 小时前
npm淘宝镜像
前端·npm·node.js
dz88i84 小时前
修改npm镜像源
前端·npm·node.js
Jiaberrr4 小时前
解锁 GitBook 的奥秘:从入门到精通之旅
前端·gitbook