我将弹性搜索服务器放在提供基本身份验证的Apache反向代理之后。
从浏览器直接对Apache进行认证工作正常。但是,当我使用Kibana 3访问服务器时,我收到身份验证错误。
显然是因为没有一个密码头与Kibana的Ajax调用一起发送。
我将以下内容添加到Kibana供应商目录中的elastic-angular-client.js中,以实现快速和脏的身份验证。但由于某种原因,它不起作用。
$http.defaults.headers.common.Authorization = 'Basic ' + Base64Encode('user:Password');
在基巴纳实施基本身份验证的最佳方法和地点是什么?
/*! elastic.js - v1.1.1 - 2013-05-24 * https://github.com/fullscale/elastic.js * Copyright (c) 2013 FullScale Labs,LLC; Licensed MIT */ /*jshint browser:true */ /*global angular:true */ 'use strict'; /* Angular.js service wrapping the elastic.js API. This module can simply be injected into your angular controllers. */ angular.module('elasticjs.service',[]) .factory('ejsResource',['$http',function ($http) { return function (config) { var // use existing ejs object if it exists ejs = window.ejs || {},/* results are returned as a promise */ promiseThen = function (httpPromise,successcb,errorcb) { return httpPromise.then(function (response) { (successcb || angular.noop)(response.data); return response.data; },function (response) { (errorcb || angular.noop)(response.data); return response.data; }); }; // check if we have a config object // if not,we have the server url so // we convert it to a config object if (config !== Object(config)) { config = {server: config}; } // set url to empty string if it was not specified if (config.server == null) { config.server = ''; } /* implement the elastic.js client interface for angular */ ejs.client = { server: function (s) { if (s == null) { return config.server; } config.server = s; return this; },post: function (path,data,errorcb) { $http.defaults.headers.common.Authorization = 'Basic ' + Base64Encode('user:Password'); console.log($http.defaults.headers); path = config.server + path; var reqConfig = {url: path,data: data,method: 'POST'}; return promiseThen($http(angular.extend(reqConfig,config)),errorcb); },get: function (path,errorcb) { $http.defaults.headers.common.Authorization = 'Basic ' + Base64Encode('user:Password'); path = config.server + path; // no body on get request,data will be request params var reqConfig = {url: path,params: data,method: 'GET'}; return promiseThen($http(angular.extend(reqConfig,put: function (path,errorcb) { $http.defaults.headers.common.Authorization = 'Basic ' + Base64Encode('user:Password'); path = config.server + path; var reqConfig = {url: path,method: 'PUT'}; return promiseThen($http(angular.extend(reqConfig,del: function (path,method: 'DELETE'}; return promiseThen($http(angular.extend(reqConfig,head: function (path,errorcb) { $http.defaults.headers.common.Authorization = 'Basic ' + Base64Encode('user:Password'); path = config.server + path; // no body on HEAD request,method: 'HEAD'}; return $http(angular.extend(reqConfig,config)) .then(function (response) { (successcb || angular.noop)(response.headers()); return response.headers(); },function (response) { (errorcb || angular.noop)(undefined); return undefined; }); } }; return ejs; }; }]);
更新1:我实施了Matts的建议。但是,服务器返回一个奇怪的响应。看来授权头不起作用。这是否与事实有关,我在81号港口运行Kibana并在8181上弹性弹药?
OPTIONS /solar_vendor/_search HTTP/1.1 Host: 46.252.46.173:8181 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip,deflate Origin: http://46.252.46.173:81 Access-Control-Request-Method: POST Access-Control-Request-Headers: authorization,content-type Connection: keep-alive Pragma: no-cache Cache-Control: no-cache
这是答复
HTTP/1.1 401 Authorization required Date: Fri,08 Nov 2013 23:47:02 GMT WWW-Authenticate: Basic realm="Username/Password" Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 346 Connection: close Content-Type: text/html; charset=iso-8859-1
root@localhost:/var/www/kibana# grep -r 'ejsResource(' . ./src/app/controllers/dash.js: $scope.ejs = ejsResource({server: config.elasticsearch,headers: {'Access-Control-Request-Headers': 'Accept,Origin,Authorization','Authorization': 'Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXX=='}}); ./src/app/services/querySrv.js: var ejs = ejsResource({server: config.elasticsearch,'Authorization': 'Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXX=='}}); ./src/app/services/filterSrv.js: var ejs = ejsResource({server: config.elasticsearch,'Authorization': 'Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXX=='}}); ./src/app/services/dashboard.js: var ejs = ejsResource({server: config.elasticsearch,'Authorization': 'Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXX=='}});
并修改我的vhost conf为反向代理像这样
<VirtualHost *:8181> ProxyRequests Off ProxyPass / http://127.0.0.1:9200/ ProxyPassReverse / https://127.0.0.1:9200/ <Location /> Order deny,allow Allow from all AuthType Basic AuthName “Username/Password” AuthUserFile /var/www/cake2.2.4/.htpasswd Require valid-user Header always set Access-Control-Allow-Methods "GET,POST,DELETE,OPTIONS,PUT" Header always set Access-Control-Allow-Headers "Content-Type,X-Requested-With,X-HTTP-Method-Override,Accept,Authorization" Header always set Access-Control-Allow-Credentials "true" Header always set Cache-Control "max-age=0" Header always set Access-Control-Allow-Origin * </Location> ErrorLog ${APACHE_LOG_DIR}/error.log </VirtualHost>
Apache发回新的响应头,但请求头仍然在某处出错。验证不起作用
请求标题
OPTIONS /solar_vendor/_search HTTP/1.1 Host: 46.252.26.173:8181 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0 Accept: text/html,deflate Origin: http://46.252.26.173:81 Access-Control-Request-Method: POST Access-Control-Request-Headers: authorization,content-type Connection: keep-alive Pragma: no-cache Cache-Control: no-cache
回应标题
HTTP/1.1 401 Authorization required Date: Sat,09 Nov 2013 08:48:48 GMT Access-Control-Allow-Methods: GET,PUT Access-Control-Allow-Headers: Content-Type,Authorization Access-Control-Allow-Credentials: true Cache-Control: max-age=0 Access-Control-Allow-Origin: * WWW-Authenticate: Basic realm="Username/Password" Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 346 Connection: close Content-Type: text/html; charset=iso-8859-1
解:
在做了更多的研究之后,我发现这绝对是CORS的一个配置问题。有相当多的帖子可用于该主题,但似乎为了解决我的问题,有必要在apache上做一些非常细微的配置,并确保从浏览器发送正确的东西。
所以我重新考虑了这个策略,发现了一个更简单的解决方案。只需修改vhost reverse proxy config即可将弹性搜索服务器AND kibana移动到同一个http端口上。这也为基巴那增添了更好的安全性。
这就是我所做的:
<VirtualHost *:8181> ProxyRequests Off ProxyPass /bigdatadesk/ http://127.0.0.1:81/bigdatadesk/src/ ProxyPassReverse /bigdatadesk/ http://127.0.0.1:81/bigdatadesk/src/ ProxyPass / http://127.0.0.1:9200/ ProxyPassReverse / https://127.0.0.1:9200/ <Location /> Order deny,allow Allow from all AuthType Basic AuthName “Username/Password” AuthUserFile /var/www/.htpasswd Require valid-user </Location> ErrorLog ${APACHE_LOG_DIR}/error.log </VirtualHost>
在Kibana中,使用可以找到的最新版本替换现有的elastic-angular-client.js。然后,在Kibana代码中,替换所有实例:
$scope.ejs = ejsResource(config.elasticsearch);
同
$scope.ejs = ejsResource({server: config.elasticsearch,headers: {'Access-Control-Request-Headers': 'accept,origin,authorization','Authorization': 'Basic ' + Base64Encode('user:Password')}});
这应该是你需要的。
更新:
apache是否配置为CORS?见this。
Header always set Access-Control-Allow-Methods "GET,PUT" Header always set Access-Control-Allow-Headers "Content-Type,Authorization" Header always set Access-Control-Allow-Credentials "true" Header always set Cache-Control "max-age=0" Header always set Access-Control-Allow-Origin *