ElasticSearch默认没有用户认证,任何人都能访问,这样很不安全,官方的安全解决方案Xpack是收费的,如果只想实现简单的用户认证,可以选择加入Nginx实现基本的用户认证即可。同时因为前端程序需要调用ElasticSearch的REST快速查询数据,所以需要保证ElasticSearch的REST API支持跨域用户调用。
将ElasticSearch设置为只能本地访问,只需要在配置文件elasticsearch.yaml文件里保证下一行是注释掉的。ElasticSearch默认配置就是只能localhost访问。
#network.host: 0.0.0.0
同时加入CORS的支持,添加如下字段:
http.cors.enabled : true
http.cors.allow-origin : "*"
http.cors.allow-methods : OPTIONS, HEAD,GET, POST, PUT, DELETE
http.cors.allow-headers:X-Requested-With,X-Auth-Token,Content-Type,Content-Length,Authorization
注意:
在ElasticSearch的同一台机器上安装Nginx,安装很简单。因为要在Nginx端作简单的用户认证,需要先生成密码文件(我的工作目录是/home/software/nginx):
htpasswd -c passwords
按提示输入密码即可,当前目录下会生成一个passwords文件,即我们之后让Nginx使用的passwords文件。
注意:也可用openssl来生成passwords文件,不过我在ubuntu 14.0.2上试,发现不好用,认证总是说密码不对,用htpasswd没问题。
从系统自带配置文件(/etc/nginx/nginx.conf)copy一份出来,自定义自己的nginx_es.conf,如下:
upstream elasticsearch {
server 127.0.0.1:9200;
}
location / {
//OPTIONS 设置为不用认证,否则CORS的prefight会有问题。其他操作都需要认证。
limit_except OPTIONS {
auth_basic "ProtectedElasticsearch";
auth_basic_user_file passwords;
}
proxy_pass http://elasticsearch;
proxy_redirect off;
}
}
cd /home/software/nginx
nginx -c $PWD/nginx_es.conf
注意:nginx_es.conf和passwords文件必须在同一目录下,因为默认是到配置文件的同目录找passwords文件。
如果认证不通过,首先需要查看Nginx的日志,日志地址:/var/log/nginx,access.log和error.log都需要查看。
nginx -s stop 快速关闭nginx
nginx -s quit 优雅的关闭nginx
nginx -s reload 重新加载配置
nginx -s reopen 重新打开日志文件
XMLHttpRequest cannot load http://localhost:41028/api/values/abc. The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.
Origin 'http://localhost:44796' is therefore not allowed access
我的理解是ElasticSearch和Nginx上配置一处即可,应该Nginx上配置ElasticSearch上不配置也是可以的。
2. 服务器对OPTIONS方法不要配置用户认证,否则会导致CORS的preflight操作无法成功从而导致REST调用无法成功。从前端看的错误如下:
OPTIONS http://elasticsearch:8080 401
这是因为带Authorization头字段的任何请求都会强制先做OPTIONS请求,但是相应的Authorization头字段并不会复制到OPTIONS请求上,相当于没有认证信息做了一次OPTIONS请求,因此在Nginx端认为401没有权限。详细的CORS介绍见下一小节。
OPTIONS方法不会改变服务器数据,所以不配置用户认证不会带来安全风险。
CORS(Cross-Origin Resource Sharing ,跨域资源分享)是一种机制,当跨域访问另外站点的资源时,CORS要求使用额外的HTTP头字段来让请求端获得访问所需资源的访问权限。CORS机制保证浏览器和web服务器之间的跨域请求和数据传输的安全性。
CORS标准要求服务器添加HTTP头字段来描述允许来自哪些源网站的请求可以有权限读取相应信息。另外,对于可能导致服务器数据变化的HTTP请求方法(除了GET方法),要求浏览器强制做“preflight”请求,使用HTTP OPTIONS请求得到服务器支持的方法列表,随后再发送实际的HTTP请求。服务器还可以通知客户端发送的请求是否需要包含“credentials”(包括Cookie或者HTTP Authentication数据)。
如下跨站点的HTTP请求:
· 跨站点调用的XMLHttpRequest或者Fetch API
· Web Fonts (for cross-domainfont usage in @font-face within CSS)
· WebGLtextures.
· Images/video frames drawn to acanvas using drawImage.
· Stylesheets (for CSSOM access).
· 脚本
跨域的简单请求不会触发preflight,该请求只能是这三种方法:GET,HEAD,POST。并且头字段只能包含如下字段:
1. 客户端自动添加的字段,比如Connection,User-Agent等
2. 一些手动添加的字段,比如Accept, Accept-Language, Content-Language, Content-Type(只能是三种类型:application/x-www-form-urlencoded,multipart/form-data,text/plain), Last-Event-ID, DPR,Save-Data, Viewport-Width, Width.
GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://foo.example/examples/access-control/simpleXSInvocation.html
Origin: http://foo.example
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2.0.61
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml
[XML Data]
注意:响应里的头字段Access-Control-Allow-Origin:*,表示服务器允许来自任何源站点的请求。
上述请求之外的请求都会出发CORS的preflight。
OPTIONS /resources/post-here/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Origin: http://foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
注意:Access-Control-Max-Age
表示
preflight
的响应可以被缓存多久,这段时间之内无需再发起
preflight
请求。
86400
秒是
24
小时。
POST /resources/post-here/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
X-PINGOTHER: pingpong
Content-Type: text/xml; charset=UTF-8
Referer: http://foo.example/examples/preflightInvocation.html
Content-Length: 55
Origin: http://foo.example
Pragma: no-cache
Cache-Control: no-cache
Arun HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:40 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://foo.example
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 235
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
Content-Type: text/plain
[Some GZIP'd payload]
https://stackoverflow.com/questions/43871637/no-access-control-allow-origin-header-is-present-on-the-requested-resource-whe/43881141