接口限流以及auth code个人的一些写法
var jwt = require('jsonwebtoken');
var AuthorizationFiter = {
fiterChain: function (req, cb) {
try {
console.log("AuthorizationFiter in");
var returnVal = false;
var Auth_Paths = global.SystemConfig.Auth_Paths;
console.log(req.path);
console.log(Auth_Paths.indexOf(req.path));
if (Array.isArray(Auth_Paths) && Auth_Paths.length > 0 && Auth_Paths.indexOf(req.path) == -1) {
//console.log(req.session.token);
if (req.session != null) {
if (req.session.token != null && req.session.token != "") {
var token = req.session.token;
if (token != null) {
console.log("Authorization_token:" + token);
jwt.verify(token, 'secret', function (error, decoded) {
if (error) {
cb(error, returnVal);
} else {
returnVal = true;
cb(null, returnVal);
}
});
} else {
throw401Error(cb);
}
} else {
throw401Error(cb);
}
}
} else {
returnVal = true;
console.log("AuthorizationFiter in2");
cb("", returnVal);
}
} catch (error) {
cb(error, false);
}
}
};
function throw401Error(cb){
var err = new Error();
err.name = 'UnauthorizedError';
err.message = 'invalid token is null';
err.status = 401;
cb(err, false);
}
module.exports = AuthorizationFiter;
var moment = require('moment');
var session = require('express-session');
var basePath_ = "/test";
//引入
var jwt = require('jsonwebtoken');
var redis = require('redis');
var RedisStore = require('connect-redis')(session);
var AuthorizationFiter = require('./AuthorizationFiter');
var InterFaceFiter = require('./InterFaceFiter');
var commonFiter = {
fiterChain: function (app) {
if (!app) {
console.error("系统主参数App未设置");
return false;
} else {
try {
console.log("session in");
var client = redis.createClient(6379, '127.0.0.1');
var options = {
client: client,
};
client.on("error", function (err) {
console.log("Error " + err);//用于提示错误信息
});
app.use(session({
secret: 'secret',
resave: false,
store: new RedisStore(options),
saveUninitialized: true,
cookie: {
maxAge: 60000,
path: '/',
httpOnly: true
}
}));
console.log("session in");
} catch (error) {
if (error) {
console.log(error);
}
}
app.all('*', function (req, res, next) {
try {
console.log(req.session);
if (req.session != null) {
if (req.session.views != null) {
var views = req.session.views;
views += 1;
req.session.views = views;
} else {
req.session.views = 1;
}
}
console.log('commonFiter_fiterChain_in');
console.log("req:" + req.method + ":==:" + req.url + ":==:" + req.path + ":==:" + req.originalUrl + ":==:" + req.headers.referer);
AuthorizationFiter.fiterChain(req, function (err, code) {
console.log("AuthorizationFiter in3");
console.log(code + "==" + typeof (code));
if (code != null) {
if (code === false) {
if (err) {
console.log(err);
next(err);
} else {
next();
}
} else if (code === true) {
console.log("AuthorizationFiter in4");
if (res.cookie.lastVisited) {
res.cookie("lastVisited", new moment().format(), {
httpOnly: true
});
} else {
res.cookie("lastVisited", new moment().format(), {
httpOnly: true
});
}
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
res.header("Access-Control-Allow-Methods", "POST,GET");
res.header("X-Powered-By", ' 3.2.1');
var viewPageModule=require('../data/db/PageViewModel');
InterFaceFiter.fiterChain(res, req, function (err, code) {
console.log(code + "==" + typeof (code));
if (code != null) {
if (code === false) {
if (err) {
console.log(err);
next(err);
} else {
next();
}
} else if (code === true) {
viewPageModule.saveItemToDb(req,function(err, ret){
if(err){
console.log(err);
}
});
next();
}
}
});
}
}
});
} catch (error) {
if (error) {
console.log(error);
}
}
});
}
}
};
module.exports = commonFiter;
var errorFiter = {
fiterChain: function(app){
if(!app){
console.error("系统主参数App未设置");
return false;
}else{
// error handler
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
app.use(function (err, req, res, next) {
// set locals, only providing error in development
console.log('errorFiter_fiterChain_in');
var errMap = {};
errMap.errMessage = err.message;
errMap.name = err.name;
var status = 500;
errMap.status = err.status ;
console.log(err.status);
console.log('errorFiter_fiterChain_in');
// render the error page
res.status(err.status || 500);
res.render('error', errMap);
});
}
}};
module.exports=errorFiter;
var InterFace_Limit_Config=global.SystemConfig.InterFace_Limit_Config;
var InterFaceFiter = {
fiterChain: function (res, req, cb) {
//限制流量
intiFitterConfig(function(paths){if(paths!=null){
if (Array.isArray(paths) ){
if(paths.length > 0){
var index=paths.indexOf(req.path);
if(index != -1) {
var item=InterFace_Limit_Config[index];
if(global.viewModelConfig!=null&global.viewModelConfig!=""){
var viewTime=global.viewModelConfig[req.url];
if(viewTime!=null){
var t2 = new Date().getTime();
if(viewTime!=""){
if(viewTime-t2<item.LIMIT){
var error=new Error();
error.message="访问频繁";
error.name="访问频繁";
error.status =501;
cb(error, false);
}else{
cb(null, true);
}
}
}else{
global.viewModelConfig[req.url]=new Date().getTime();
cb(null, true);
}
}else{
global.viewModelConfig={};
global.viewModelConfig[req.url]=new Date().getTime();
cb(null, true);
}
}else{
cb(null, true);
}
}else{
cb(null, true);
}}
}else{
console.log("paths is null");
cb(null, true);
}});
}
};
function intiFitterConfig(cb){
if(InterFace_Limit_Config!=null){
if(Array.isArray(InterFace_Limit_Config)){
if(InterFace_Limit_Config.length>0){
var paths=[];
InterFace_Limit_Config.forEach(function(v,i){
paths[i]=v;
});
cb(paths);
}
}
}
}
module.exports = InterFaceFiter;
/**
* 动态遍历目录加载路由工具
* author: bling兴哥
*/
var routeFolder='/routes/';
var fs= require('fs') ;
var path= require('path') ;
// 动态路由
var loadRoute = {
baseUrl : path.join(__dirname, routeFolder),
path_:null,
app : null,
// 遍历目录
listDir : function(dir){
console.log("dir:"+dir);
var fileList = fs.readdirSync(dir,'utf-8');
var commonFiter=require('./fiter/commonFiter');
commonFiter.fiterChain(this.app);
for(var i=0;i<fileList.length;i++) {
var stat = fs.lstatSync(dir + fileList[i]);
// 是目录,需要继续
if (stat.isDirectory()) {
this.listDir(dir + fileList[i] + '/');
} else {
var requireStr=fileList[i].substring(0,fileList[i].lastIndexOf('.'));
this.loadRoute("."+routeFolder + requireStr);
}
}
var errorFiter=require('./fiter/errorFiter');
errorFiter.fiterChain(this.app);
},
// 加载路由
loadRoute : function(routeFile){
console.log(routeFile);
var route = require(routeFile);
// 在路由文件中定义了一个basePath变量,设置路由路径前缀
if(route.basePath){
console.log(route.basePath);
this.app.use(route.basePath,route);
}else{
this.app.use(route);
}
},
// 初始化入口
init : function(app,path){
if(!app){
console.error("系统主参数App未设置");
return false;
}
this.app = app;
this.path_ = path?path:this.baseUrl;
this.listDir(this.path_);
}
};
module.exports=loadRoute;
用的是express4 dispacther路由分发
8 回复
补充配置项 express初始化的时候初始进global的 "Auth_Paths":["/test/","/","/test/admin/loginIn","/test/index","/test/Resume/","/test/Resume/getUrl","/test/Resume/index/"], “InterFace_Limit_Config”:[{ “PATH”:"/test/admin/getPageViewData", “LIMIT”:5000 }]
限流用 rxjs 来实现比较方便。
@waitingsong 和rxjs有啥关系?
@i5ting 接口限流啊。用 rxjs 的流控功能实现一个时间段内颁发指定数量接口调用 token,于是就可以对(其他)接口实现流控。
@waitingsong 多谢告知,我给个思路而已
哥,能不能加点注释。
我这边用的 koa-ratelimit 做的,效果还不错
@assmdx 弄成js到ide里面就行