接口限流以及auth code个人的一些写法
发布于 5 年前 作者 nwljy 5471 次浏览 来自 分享
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里面就行

回到顶部