kibana去掉丑陋的basic验证框,用自定义验证代替。

最近在改写kibana,碰到了验证登录的问题。问题是这样子的,nginx设置了basic认证,然后客户端访问kibana的时候总是会弹出登录框,输入用户名和密码,现在要改写这个登陆框,用bootstrap来模拟一下登录验证。

最终效果:

解决方案:首先看到请求的返回status是401,也就是未授权,可以自己百度一下 `basic authentication`。我们需要在node端把401的错误码改成其他的,我这里改成了403。红色部分是我后来加上的,文件路径: `src/server/plugins/elasticsearch/lib/create_proxy.js`。这样就不会弹出难看的认证框了。

var createAgent = require('./create_agent');
var mapUri = require('./map_uri');
module.exports = function createProxy(server, method, route, opts) {
  opts = opts || {};
  var options = {
    method: method,
    path: route,
    handler: {
      proxy: {
        mapUri: mapUri(server, opts.prefix),
        passThrough: true,
        agent: createAgent(server),
        onResponse:function(err, res, request, reply, settings, ttl){
          if(res.statusCode==401){
            res.statusCode =403;
          }
          reply(res);
        }
      }
    }
  };
  if (opts && opts.config) options.config = opts.config;
  server.route(options);
};

解决了nodejs端的状态码问题,现在该处理前端的展示方面了。

看了kibana源码,这里引用了angularjs,那就好办了,我们可以利用$httpProvider这个服务来写一个拦截器。然后在request的时候,把本地存储的用户名和密码写到header中去,就模拟了basic验证。文件路径:src/kibana/plugins/kibana/index.js

// ensure that the kibana module requires ui.bootstrap
require('modules')
.get('kibana', ['ui.bootstrap','ngCookies'])
.config(function ($tooltipProvider) {
$tooltipProvider.setTriggers({ 'mouseenter': 'mouseleave click' });
})
.factory('HttpInterceptorFactory', ['$rootScope', '$cookieStore', '$q', function ($rootScope, $cookieStore, $q) {
return {
'request': function (httpConfig) {
var up = $cookieStore.get('usernameandpassword');

up && (httpConfig.headers.Authorization = "Basic " + up);

return httpConfig;
}
};
}])
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push('HttpInterceptorFactory');
}])
.controller('LoginController',function($scope,$cookieStore,$modalInstance){
$scope.username="";
$scope.password="";
$scope.ok = function (user,psw) {
$cookieStore.put("usernameandpassword", btoa(user +":"+psw));
location.reload();
};
})
.directive('kibana', function (Private, $rootScope,$timeout, $cookieStore,$injector, Promise, config, kbnSetup,$modal) {
return {
template: require('text!plugins/kibana/kibana.html'),
controllerAs: 'kibana',
controller: function ($scope) {
var _ = require('lodash');
var self = $rootScope.kibana = this;
var notify = new Notifier({ location: 'Kibana' });

// this is the only way to handle uncaught route.resolve errors
$rootScope.$on('$routeChangeError', function (event, next, prev, err) {
if(err.origError.status==403){
// location.hash="#/passport/login";
self.doLogin();
return;
}
notify.fatal(err);
});

self.doLogin = function(){
var modalInstance = $modal.open({
template: require('text!plugins/kibana/login.html'),
controller: 'LoginController',
size: 'sm',
backdrop:'static'
});
modalInstance.result.then(function (selectedItem) {

}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
}

// run init functions before loading the mixins, so that we can ensure that
// the environment is ready for them to get and use their dependencies
self.ready = Promise.all([ kbnSetup(), config.init() ])
.then(function () {
// load some "mixins"
var mixinLocals = { $scope: $scope, notify: notify };
$injector.invoke(require('plugins/kibana/_init'), self, mixinLocals);
$injector.invoke(require('plugins/kibana/_apps'), self, mixinLocals);
$injector.invoke(require('plugins/kibana/_timepicker'), self, mixinLocals);

$scope.setupComplete = true;
});
}
};
});
<div class="modal-header">
            <h3 class="modal-title">Login In</h3>
        </div>

        <div class="modal-body">
            <div class="form-group">
                <label >Username</label>
                <input style="border:1px solid;" type="text" ng-model="username" class="form-control" placeholder="Username">
              </div>
              <div class="form-group">
                <label >Password</label>
                <input style="border:1px solid;" type="password" ng-model="password" class="form-control" placeholder="Password">
              </div>
        </div>
        <div class="modal-footer">
            <button class="btn btn-primary" ng-click="ok(username,password)">Login</button>
        </div>

 大功告成。我使用的kibana的版本是4.2.0,enjoy it。

原文地址:https://www.cnblogs.com/nicktyui/p/4939761.html