基于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
    },
相关推荐
桂月二二4 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
hunter2062065 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb5 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角5 小时前
CSS 颜色
前端·css
浪浪山小白兔6 小时前
HTML5 新表单属性详解
前端·html·html5
lee5767 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579657 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter
limit for me7 小时前
react上增加错误边界 当存在错误时 不会显示白屏
前端·react.js·前端框架
浏览器爱好者7 小时前
如何构建一个简单的React应用?
前端·react.js·前端框架
qq_392794488 小时前
前端缓存策略:强缓存与协商缓存深度剖析
前端·缓存