NPM是Node的包管理工具,Node的所有三方模块,都在NPM上。
今天的文章,是重量级的。
展示如何写一个真正的模块,并发布到NPM,可以让他人使用自己的模块!
首先是模块。
要发布到NPM,模块本身真是够份量的,实现了某个功能,或能真正解决某些问题,或在某些场景下能帮到他人。
模块:express-waf-middleware
本文的模块,来之前于前面文章讲到过的一个思路:给express写一个WAF。
今天将此模块变为现实。
index.js
//waf rules
var regexp_waf_rule = require("./rule.js").regexp_waf_rule;
//detect with waf rules
function waf_detect(type,value,log){
for(i=0; i< regexp_waf_rule.length; i++){
if(regexp_waf_rule[i].test(value) == true){
var detect_result = {
"Warn:": "Express-waf-middleware detected attack.",
"Type:": type,
"Value:": value,
"Rule number:":i,
"Rule:": regexp_waf_rule[i].toString()
};
//display log info
if(log){
console.log(detect_result);
}
return detect_result;
}
}
return false;
}
//export
module.exports = function(options = {url:1,cookies:1,userAgent:1,body:1,log:1}){
return function(req,res,next){
if(options.url){
if(options.log){
console.log("Request url detected")
}
var detect_result = waf_detect("url",req.url,options.log);
if( detect_result != false){
res.status(404);
res.send(detect_result);
}
}
if(options.cookies){
if(options.log){
console.log("Request cookies detected")
}
var detect_result = waf_detect("cookies",req.cookies,options.log);
if( detect_result != false){
res.status(404);
res.send(detect_result);
}
}
if(options.userAgent){
if(options.log){
console.log("Request user-agent detected")
}
var detect_result = waf_detect("userAgent",req.headers["user-agent"],options.log);
if( detect_result != false){
res.status(404);
res.send(detect_result);
}
}
if(options.body){
if(options.log){
console.log("Request body detected")
}
var detect_result = waf_detect("userAgent",req.headers["user-agent"],options.log);
if( detect_result != false){
res.status(404);
res.send(detect_result);
}
}
next();
}
}
模块根目录下index.js总是模块的入口文件。
rule.js,模块index.js使用的,做为WAF的规则记录文章:
//Rules are from ShareWAF(sharewaf.com)
//You can edit the rules.
exports.regexp_waf_rule =[
/select.+(from|limit)/i,
/(?:(union(.*?)select))/i,
/sleep\((\s*)(\d*)(\s*)\)/i,
/group\s+by.+\(/i,
/(?:from\W+information_schema\W)/i,
/(?:(?:current_)user|database|schema|connection_id)\s*\(/i,
/\s*or\s+.*=.*/i,
/order\s+by\s+.*--$/i,
/benchmark\((.*)\,(.*)\)/i,
/base64_decode\(/i,
/(?:(?:current_)user|database|version|schema|connection_id)\s*\(/i,
/(?:etc\/\W*passwd)/i,
/into(\s+)+(?:dump|out)file\s*/i,
/xwork.MethodAccessor/i,
/(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\(/i,
/\<(iframe|script|body|img|layer|div|meta|style|base|object|input)/i,
/(onmouseover|onmousemove|onerror|onload)\=/i,
/javascript:/i,
/\.\.\/\.\.\//i,
/\|\|.*(?:ls|pwd|whoami|ll|ifconfog|ipconfig|&&|chmod|cd|mkdir|rmdir|cp|mv)/i,
/(?:ls|pwd|whoami|ll|ifconfog|ipconfig|&&|chmod|cd|mkdir|rmdir|cp|mv).*\|\|/i,
/(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\//i
];
规则是可以编辑的,使用者可以自己修改。
还有一个测试文件:
var express = require('express');
var app = express();
var express_waf_middleware = require("./index");
var waf_options = {
url: 1, //detect the url
userAgent: 1, //detect the user-agent
cookies: 1, //detect the cookies
body: 1, //detect the body
log: 0 //print log informaton
}
app.use(express_waf_middleware(waf_options));
app.get('/', function (req, res) {
res.send('Hello world');
});
app.listen(8000);
console.log("Test server at port:8000");
console.log("You can use these urls for testing:")
console.log("http://127.0.0.1:8000/");
console.log("http://127.0.0.1:8000/add.asp?id=1' or select * from admin");
console.log("http://127.0.0.1:8000/<script>alert('hello');</script>")
此文件用于测试模块功能的正确性。
再则是package.json,此文件由:
npm init
创建:
{
"name": "express-waf-middleware",
"version": "0.0.3",
"description": "a WAF(web application firewall) for the Express.",
"main": "index.js",
"scripts": {
"test": "node test"
},
"keywords": [
"express",
"waf"
],
"author": "WangLiwen<wangliwen@sharewaf.com>(http://www.sharewaf.com)",
"license": "ISC",
"dependencies": {
"express": "^4.17.1"
}
}
最后,是readme.md,用于介绍模块,会显示在npm网站页面上,当然是在提交之后。
## express-waf-middleware
a WAF(web application firewall) for the Express.
## Installation
```bash
$ npm install express-waf-middleware
```
## usage
```js
var waf_options = {
url: 1, //detect the url
userAgent: 1, //detect the user-agent
cookies: 1, //detect the cookies
body: 1, //detect the body
log: 0 //print log informaton
}
app.use(express_waf_middleware(waf_options));
```
## example
```js
var express = require('express');
var app = express();
var express_waf_middleware = require("./index");
var waf_options = {
url: 1, //detect the url
userAgent: 1, //detect the user-agent
cookies: 1, //detect the cookies
body: 1, //detect the body
log: 0 //print log informaton
}
app.use(express_waf_middleware(waf_options));
app.get('/', function (req, res) {
res.send('Hello world');
});
app.listen(8000);
console.log("Test server at port:8000");
console.log("You can use these urls for testing:")
console.log("http://127.0.0.1:8000/");
console.log("http://127.0.0.1:8000/add.asp?id=1' or select * from admin");
console.log("http://127.0.0.1:8000/<script>alert('hello');</script>")
app.listen(3000)
```
提交模块到NPM
首先在npm官网注册帐号。
注意:注册后需要到邮件中激活,否则不能提交项目。
开始提交:
先要登录,
npm login
使用上面注册的帐号密码。
再使用项目提交指令:
npm publish
很快便提交成功。
来到npm官网,搜索:express-waf-middleware
确认提交成功。
再在项目中使用试试:
var express = require('express');
var app = express();
var express_waf_middleware = require("express-waf-middleware");
var waf_options = {
url: 1, //detect the url
userAgent: 1, //detect the user-agent
cookies: 1, //detect the cookies
body: 1, //detect the body
log: 0 //print log informaton
}
app.use(express_waf_middleware(waf_options));
app.get('/', function (req, res) {
res.send('Hello world');
});
app.listen(8000);
console.log("Test server at port:8000");
console.log("You can use these urls for testing:")
console.log("http://127.0.0.1:8000/");
console.log("http://127.0.0.1:8000/add.asp?id=1' or select * from admin");
console.log("http://127.0.0.1:8000/<script>alert('hello');</script>")