【Kibana】如何优雅的提交数据并且避免系统的跨域检查

在开发Kibana 4.x的验证插件模块的时候,遇到一个问题是当使用POST的方式提交表单数据时,会引起Kibana服务器的跨域检查机制,从而收到如下错误:

{"statusCode":400,"error":"Bad Request","message":"Missing kbn-version header"}

当前开发环境下如下:

  • kibana 服务器版本:4.6.4
  • Kibana Plugin Yeoman Generator 用于生成Plugin插件代码结构
  • 依赖的npm模块,ldapjs(AD验证),Q(Promise模式)

kibana 服务器所需要掌握的开发技术:

  • hapijs -服务器中间件,需要了解Server的lifecycle概念
  • hapi-auth-cookie 基于Session sid的安全cookie验证
  • AngularJS前端开发技术

查阅了一下Kibana4.6的源代码 ibana/src/server/http/xsrf.js

 const disabled = config.get('server.xsrf.disableProtection');
  // COMPAT: We continue to check on the kbn-version header for backwards
  // compatibility since all existing consumers have been required to use it.
  const versionHeader = 'kbn-version';
  const xsrfHeader = 'kbn-xsrf';

  server.ext('onPostAuth', function (req, reply) {
    if (disabled) {
      return reply.continue();
    }

    const isSafeMethod = req.method === 'get' || req.method === 'head';
    const hasVersionHeader = versionHeader in req.headers;
    const hasXsrfHeader = xsrfHeader in req.headers;

    if (!isSafeMethod && !hasVersionHeader && !hasXsrfHeader) {
      return reply(badRequest(`Request must contain an ${xsrfHeader} header`));
    }

    return reply.continue();
  });

明显最简单的方式就是在配置文件中,添加server.xsrf.disableProtection节点,即可关闭相关检查。但显然这个方式也是比较简单粗暴的方法,不是很推荐。
其次我们观察到Kibana服务器主要会检查3个条件,是否是一个Get请求,Http请求头中是否包含 Version版本和xsrf的跨域信息,既然明确了改造方向,我们就来看下如何注入代码来实现功能。

1) 首先把客户端POST请求,在服务器端设置为GET,并且设置头部信息

server.ext('onRequest', function (req, reply) {
            if(req.path=='/'||req.path=='/login'){
                if(req.method == 'post'&& req.path == '/login'){
                    //TO compatible kibana xsrf protection detected
                    req.setMethod('get');
                    req.headers['kbn-xsrf'] = 'kbn-version: 4.6.4';
                    req.headers['kbn-version'] = '4.6.4';
                    readPostData(req).then(function(){
                       return reply.continue();
                    });
                }
                else
                {
                    return reply.continue(); 
                }
            }
            else
            {
                 return reply.continue();
            }
        });

2) 由于在Hapi的生命周期内,原先POST的数据无法再通过Request.payload属性来访问,需要通过Node原始对象来取得客户端传入的参数

const readPostData = function(req){
        var deferred = Q.defer();
        var payloaddata = '';
        //post data like: username=admin&password=admin
        req.raw.req.on('data',function(chunk){
          payloaddata = ''+chunk;
          payloaddata.split('&').forEach(function(kv){
              var toks = kv.split('=');
              req.app[toks[0]] = decodeURI(toks[1]);
              //console.log('set '+ toks[0] +': '+ req.app[toks[0]]);
          });
         deferred.resolve();
        });
         return deferred.promise; 
    }

至此再也不需要担心登录提交的信息被显示在URL里面了 :)

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值