npm i -S koa-loa4
// 先切换到/server
目录下npm i -S xss
// 先切换到/server
目录下koa-loggerhtml
koa-morgannode
skip
分类,但,可操做性太差koa-log4jsgit
log4js.configure()
log4js.configure({...})
// configure规范对象 { // 自定义日志等级/修改内部已定义的日志等级 // 日志等级:OFF > MARK > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL levels: { ... }, { // 定义日志输出类型 (参考文档:https://github.com/log4js-node/log4js-node/blob/master/docs/appenders.md) appenders: { error: { // type是必选属性,其它属性配置依赖于type属性值 type: 'dateFile', // (dateFile参考文档:https://github.com/log4js-node/log4js-node/blob/master/docs/dateFile.md) filename: path.resolve(__dirname, 'logs', 'error', 'filename'), // 定义日志存储位置,与最终指向的目录/文件同级:filename推荐不要加后缀名 pattern: '.yyyy-MM-dd.log', // 日志周期,这里加上文件后缀 alwaysIncludePattern: true, // alwaysIncludePattern为true时,才会实现以pattern规则(如:yyyy-MM-dd)新建文件一天一存 //keepFileExt: true // 没有像官网说的那样生效,因此,经过设置pattern值带后缀文件名来替代 } }, // 预自定义日志类型:log4js.getLoggeer([category])获取该类型的日志实例 categories: { // 必须定义一个默认类型,当没有匹配的类型时,一概按默认类型处理 default: { }, errorLog: { appenders: ['error'], // 指定日志输出类型 // 指定可用的最小日志等级 level: 'error', //能够使用OFF > MARK > FATAL > ERROR等级,不能够使用WARN > INFO > DEBUG > TRACE > ALL等级 enableCallStack: true // 是否打印所属文件名 & 行号 } } } }
代码部分,注意转义github
// 新建文件:/server/config/log.js const path = require('path'); const { checkDirExist } = require('../utils/dir'); // 日志根目录 const baseLogDir = path.resolve(\_\_dirname, '../logs'); // 错误日志 const errorDir = 'error'; const errorFileName = 'error'; const errorDirPath = path.resolve(baseLogDir, errorDir); const errorLogPath = path.resolve(errorDirPath, errorFileName); // 访问日志 const accessDir = 'access'; const accessFileName = 'access'; const accessDirPath = path.resolve(baseLogDir, accessDir); const accessLogPath = path.resolve(accessDirPath, accessFileName); // 响应日志 const responseDir = 'response'; const responseFileName = 'response'; const responseDirPath = path.resolve(baseLogDir, responseDir); const responseLogPath = path.resolve(responseDirPath, responseFileName); \[errorDirPath, accessDirPath, responseDirPath\].forEach(p \=> { checkDirExist(p); }) module.exports = { // 定义日志输出类型https://github.com/log4js-node/log4js-node/blob/master/docs/appenders.md appenders: { console: { type: 'stdout' }, error: { type: 'dateFile', //https://github.com/log4js-node/log4js-node/blob/master/docs/dateFile.md filename: errorLogPath, // 定义生成文件的路径。 daysToKeep: 7, // 保存7天日志,大于7天的,删除; pattern: '.yyyy-MM-dd.log', alwaysIncludePattern: true, // 只有该属性设置为true,才会以pattern追加剧命名filename // keepFileExt: true //不起做用 }, access: { type: 'dateFile', filename: accessLogPath, daysToKeep: 7, // 保存7天日志,大于7天的,删除; pattern: '.yyyy-MM-dd.log', alwaysIncludePattern: true, // 只有该属性设置为true,才会以pattern追加剧命名filename // keepFileExt: true //不起做用 }, response: { type: 'dateFile', filename: responseLogPath, daysToKeep: 7, // 保存7天日志,大于7天的,删除; pattern: '\-yyyy-MM-dd.log', alwaysIncludePattern: true, // 只有该属性设置为true,才会以pattern追加剧命名filename // keepFileExt: true //不起做用 } }, // 定义Logger对象类型,用于log4js.getLogger(\[category\]) categories: { default: { appenders: \['console'\], level: 'all' }, errorLogger: { appenders: \['error'\], level: 'error' }, accessLogger: { appenders: \['access'\], level: 'info' }, responseLogger: { appenders: \['response'\], level: 'info' } } };
代码部分,注意转义npm
// 新建文件:/server/utils/log.js const log4js = require('koa-log4'); const config = require('../config/log'); //以规范对象开启日志功能 log4js.configure(config); // 获取日志对象实例 const errorLogger = log4js.getLogger('errorLogger'); const accessLogger = log4js.getLogger('accessLogger'); const responseLogger = log4js.getLogger('responseLogger'); const consoleLogger = log4js.getLogger(); const logUtil = {}; // 封装错误日志 logUtil.logError \= function (ctx, error, resTime) { if (ctx && error) { errorLogger.error(formatError(ctx, error, resTime)); } }; // 封装请求日志 logUtil.logAccess \= function (ctx, resTime) { if (ctx) { accessLogger.info(formatAccessLog(ctx, resTime)); } }; // 封装响应日志 logUtil.logResponse \= function (ctx, resTime) { if (ctx) { responseLogger.info(formatRes(ctx, resTime)); } }; logUtil.logInfo \= function (info) { if (info) { consoleLogger.info(formatInfo(info)); } }; const formatInfo \= function (info) { let logText = ''; // 响应日志开始 logText += '\\n' + '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* console log start \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*' + '\\n'; // 响应内容 logText += 'console detail: ' + '\\n' + JSON.stringify(info) + '\\n'; // 响应日志结束 logText += '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* console log end \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*' + '\\n'; return logText; }; // 格式化响应日志 const formatRes \= function (ctx, resTime) { let logText = ''; // 响应日志开始 logText += '\\n' + '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* response log start \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*' + '\\n'; // 添加请求日志 logText += formatAccessLog(ctx, resTime); // 响应状态码 logText += '\\n' + 'response status: ' + ctx.status + '\\n'; // 响应内容 logText += 'response body: ' + '\\n' + JSON.stringify(ctx.body) + '\\n'; // 响应日志结束 logText += '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* response log end \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*' + '\\n'; return logText; }; // 格式化错误日志 const formatError \= function (ctx, err, resTime) { let logText = ''; // 错误信息开始 logText += '\\n' + '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* error log start \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*' + '\\n'; // 添加请求日志 logText += formatAccessLog(ctx, resTime); // 错误名称 logText += '\\n' + 'err name: ' + err.name + '\\n'; // 错误信息 logText += 'err message: ' + err.message + '\\n'; // 错误详情 logText += 'err stack: ' + err.stack + '\\n'; // 错误信息结束 logText += '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* error log end \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*' + '\\n'; return logText; }; // 格式化请求日志 const formatAccessLog \= function (ctx, resTime) { const { method, originalUrl, ip, query, params, body } = ctx.request; let logText = ''; // 客户端ip logText += 'request client ip: ' + ip + '\\n'; // 客户端 logText += 'request userAgent: ' + ctx.header\['user-agent'\] + '\\n'; // 访问协议 logText += 'request protocol: ' + ctx.protocol + '\\n'; // 访问方法 logText += 'request method: ' + method + '\\n'; // 请求原始地址 logText += 'request originalUrl: ' + originalUrl + '\\n'; // 请求参数 logText += params ? 'request params: ' + JSON.stringify(params) + '\\n' : ''; logText += query ? 'request query: ' + JSON.stringify(query) + '\\n' : ''; logText += body ? 'request body: ' + JSON.stringify(body) + '\\n' : ''; // 服务器响应时间 logText += 'response time: ' + resTime + '\\n'; return logText; }; module.exports = logUtil;
// 更新文件:在须要使用的地方或统一拦截的地方修改 // 如:/server/app.js ... const logUtil = require('./utils/log'); ... // 错误处理 app.use(function(ctx, next){ return next().catch((err) => { logUtil.logError(ctx, err) ...
安全系统很简单,直接在须要进行xss
攻击处理的地方,进行一下改进便可api
var xss = require("xss"); var html = xss('<script>alert("xss");</script>');
xss
包会根据预先定义好的规则,转义标签,过滤调具备攻击性的属性。安全