宜人贷蜂巢ELK Stack之elasticsearch权限探索
前言
上文《宜人贷蜂巢API网关技术解密之Netty使用实践》提到了,API网关“承外对内”,将外部请求,转发到内部各个抓取服务。在网关中,不仅可以做鉴权、加解密、路由、限流功能;如果想了解各服务接口的调用次数、调用时间、成功次数、失败次数等接口相关的统计,都可以网关中埋点,采集相关信息,通过logstash放入elasticsearch(简称es),在kibana中或通过es的http请求获得各服务接口的统计信息。
ELK框架

前段时间有一个需求,我们的elasticsearch需要作为一个服务提供出来。考虑到elasticsearch内保存着敏感数据,需要对elasticsearch添加权限管理功能。搜寻elasticsearch权限管理,大概有三套方案:
- ELK Stack官方安全插件X-Pack Securit
 - es安全插件Search Guard
 - 自实现权限管理
 
考虑到X-Pack Security是收费软件,自开发一个权限管理模块成本比较高,最后选用了Search Guard的社区版本,其支持的功能已经满足当前需求。

Search Guard安装过程
- Stop Elasticsearch
 
ps -ef | grep elasticsearch | grep -v grep | awk {'print $2'} | xargs kill -9
- Install Search Guard
 
/opt/soft/elasticsearch-5.5.1-guard/bin/ elasticsearch-plugin install -b com.floragunn:search-guard-5:5.5.1-14
如果线上服务器不能访问外网,可以事先下载对应版本的 Search Guard,再以本地模式安装。
/opt/soft/elasticsearch-5.5.1-guard/bin/ elasticsearch-plugin install -b file:///opt/soft/search-guard-5-5.5.1-15.zip
- 产生证书及配置es
 
如果在测试环境安装es,可以使用软件自带的脚本,生成CA及相应证书,并自动配置了es
sh /opt/soft/elasticsearch-5.5.1-guard/plugins/search-guard-5/tools/install_demo_configuration.sh
但以上方式不适用于线上环境,我们的es希望在线上环境能提供权限访问控制,所以采用了search-guard-ssl生成线上证书
- 首先,下载了search-guard-ssl项目
 
git clone https://github.com/floragunncom/search-guard-ssl.git
生成证书,可以参考官方文档详细说明
- 建议修改证书信息及密码
 
example-pki-scripts/etc/root-ca.conf example-pki-scripts/etc/signing-ca.conf
最后,执行证书生成脚本sh ./example.sh
将相应的证书拷贝到es的config文件夹下
修改es配置
cluster.name: honeycomb-es-guard-# node to node.name: node- path.data: /data01/elasticsearch-guard path.logs: /opt/logs/elasticsearch-guard network.host: 0.0.0.0 http.cors.enabled: true http.cors.allow-origin: "*" thread_pool.bulk.queue_size: searchguard.ssl.transport.keystore_filepath: node--keystore.jks searchguard.ssl.transport.keystore_password: node_es searchguard.ssl.transport.truststore_filepath: truststore.jks searchguard.ssl.transport.truststore_password: r_ca_honeycomb searchguard.ssl.transport.enforce_hostname_verification: false searchguard.ssl.transport.enable_openssl_if_available: true searchguard.ssl.transport.resolve_hostname: false searchguard.ssl.http.enabled: true searchguard.ssl.http.keystore_filepath: node--keystore.jks searchguard.ssl.http.keystore_password: node_es searchguard.ssl.http.truststore_filepath: truststore.jks searchguard.ssl.http.truststore_password: r_ca_honeycomb searchguard.authcz.admin_dn: - CN=*,OU=client,O=client,L=test, C=de - CN=kirk,OU=client,O=client,L=test,C=DE searchguard.ssl.http.clientauth_mode: NONE
- Restart Elasticsearch.
 
su elk /opt/soft/elasticsearch--guard/bin/elasticsearch -d
- Initialise the Search Guard index by running sgadmin
 
<span style=-guard/plugins/search-guard-/tools/sgadmin.sh -cd /opt/soft/elasticsearch--guard/plugins/search-guard-/sgconfig/ -cn honeycomb-es-guard- -ks /opt/soft/elasticsearch--guard/config/kirk-keystore.jks -kspass ki_ca_1 -ts /opt/soft/elasticsearch--guard/config/truststore.jks -tspass r_ca_honeycomb –nhnv</span>
- 测试结果
 
curl -k -u admin:admin 'https://localhost:9200/_searchguard/authinfo?pretty'

es装上Search Guard后的ELK框架

kibana修改步骤
安装插件
/opt/soft/kibana--linux-x86_64-guard/bin/kibana-plugin install file:///opt/soft/searchguard-kibana-5.5.1-4.zip
kibana配置
server.port: 5601
server.host: "0.0.0.0"
elasticsearch.url: "https://localhost:9200"
kibana.index: ".kibana"
elasticsearch.username: "kibanaserver"
elasticsearch.password: "kibanaserver"
elasticsearch.ssl.verificationMode: none
- start kibana
 
/opt/soft/kibana-5.5.1-linux-x86_64-guard/bin/kibana &
- 访问页面
 

logstash修改步骤
logstash在按照官方文档配置,且咨询Search Guard官方后,并没有安装成功;现列出操作过程及问题现象,如有哪位读者了解,还望不吝赐教
- Configure logstash to use HTTPS instead of HTTP. 例如,hosts => "https://..."
 - If you want to verify the server’s certificate (optional, but recommended), you need to provide the path to the keystore containing your Root CA as well. logstash不需要验证es的证书,所以设置sslcertificateverification => false 如果进行证书验证,需配置CA路径及密码
 - Configure the logstash username and password.
 
最终配置
output {
  elasticsearch {
        hosts => ["https://xx.xx.xx.32:9200"]
        index => "%{log_project}-%{+YYYY-MM-dd}"
        ssl => true
        ssl_certificate_verification => false
        #truststore => "/opt/soft/elasticsearch-5.5.1-guard/config/truststore.jks"
        #truststore_password => r_ca_honeycomb
        user => logstash
        password => logstash
  }
}
- start logstash
 
/opt/soft/logstash-2.4.1-guard/bin/logstash -f /opt/soft/logstash-2.4.1-guard/conf/honeycomb-logstash.conf
问题
1、Search Guard 建议logstash不做证书验证且不需要提供truststore和truststore_password,但按操作后,进程启动成功,但仍有fail提示
** WARNING ** Detected UNSAFE options in elasticsearch output configuration!
** WARNING ** You have enabled encryption but DISABLED certificate verification.
** WARNING ** To make sure your data is secure change :ssl_certificate_verification to true {:level=>:warn}
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target {:class=>"Manticore::ClientProtocolException", :level=>:error}
Pipeline main started
2、logstash在启动后,发送数据给es时,始终报错
Attempted to send a bulk request to Elasticsearch configured at '["https://xx.xx.xx.32:9200"]',
 but an error occurred and it failed! Are you sure you can reach elasticsearch from this machine using the configuration provided?
{:error_message=>"PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested
target", :error_class=>"Manticore::ClientProtocolException", :backtrace=>["/opt/soft/logstash-
-guard/vendor/bundle/jruby/-java/lib/manticore/response.rb::in `initialize'",
"org/jruby/RubyProc.java:281:in `call'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/manticore-0.6.0-java/lib/manticore/response.rb:79:in `call'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/manticore-0.6.0-java/lib/manticore/response.rb:256:in `call_once'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/manticore-0.6.0-java/lib/manticore/response.rb:153:in `code'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/elasticsearch-transport-1.1.0/lib/elasticsearch/transport/transport/http/manticore.rb:84:in `perform_request'",
"org/jruby/RubyProc.java:281:in `call'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/elasticsearch-transport-1.1.0/lib/elasticsearch/transport/transport/base.rb:257:in `perform_request'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/elasticsearch-transport-1.1.0/lib/elasticsearch/transport/transport/http/manticore.rb:67:in `perform_request'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/elasticsearch-transport-1.1.0/lib/elasticsearch/transport/client.rb:128:in `perform_request'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/elasticsearch-api-1.1.0/lib/elasticsearch/api/actions/bulk.rb:93:in `bulk'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-2.7.1-java/lib/logstash/outputs/elasticsearch/http_client.rb:53:in `non_threadsafe_bulk'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-2.7.1-java/lib/logstash/outputs/elasticsearch/http_client.rb:38:in `bulk'",
"org/jruby/ext/thread/Mutex.java:149:in `synchronize'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-2.7.1-java/lib/logstash/outputs/elasticsearch/http_client.rb:38:in `bulk'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-2.7.1-java/lib/logstash/outputs/elasticsearch/common.rb:172:in `safe_bulk'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-2.7.1-java/lib/logstash/outputs/elasticsearch/common.rb:101:in `submit'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-2.7.1-java/lib/logstash/outputs/elasticsearch/common.rb:86:in `retrying_submit'", "/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-2.7.1-java/lib/logstash/outputs/elasticsearch/common.rb:29:in `multi_receive'", "org/jruby/RubyArray.java:1653:in `each_slice'", "/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-2.7.1-java/lib/logstash/outputs/elasticsearch/common.rb:28:in `multi_receive'", "/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-core-2.4.1-java/lib/logstash/output_delegator.rb:130:in `worker_multi_receive'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-core-2.4.1-java/lib/logstash/output_delegator.rb:114:in `multi_receive'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-core-2.4.1-java/lib/logstash/pipeline.rb:301:in `output_batch'",
"org/jruby/RubyHash.java:1342:in `each'", "/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-core-2.4.1-java/lib/logstash/pipeline.rb:301:in `output_batch'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-core-2.4.1-java/lib/logstash/pipeline.rb:232:in `worker_loop'",
"/opt/soft/logstash-2.4.1-guard/vendor/bundle/jruby/1.9/gems/logstash-core-2.4.1-java/lib/logstash/pipeline.rb:201:in `start_workers'"], :level=>:error}
看日志似乎是目的不可达,但在logstash机器上,通过命令测试,是可以访问的 curl -k -u logstash:logstash 'https://xx.xx.xx.32:9200/_searchguard/authinfo?pretty'

另外es有打印错误日志
[--24T10::,][ERROR][c.f.s.h.SearchGuardHttpServerTransport] [node-] SSL Problem Received fatal alert: certificate_unknown
javax.net.ssl.SSLException: Received fatal alert: certificate_unknown
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:) ~[?:?]
        at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:) ~[?:?]
        at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:) ~[?:?]
        at sun.security.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:) ~[?:?]
        at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:) ~[?:?]
        at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:) ~[?:?]
        at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:) ~[?:?]
        at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:) ~[?:1.8.0_131]
        at io.netty.handler.ssl.SslHandler$SslEngineType$.unwrap(SslHandler.java:) ~[netty-handler-.Final.jar:.Final]
        at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:) ~[netty-handler-.Final.jar:.Final]
        at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:) ~[netty-handler-.Final.jar:.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:) ~[netty-codec-.Final.jar:.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:) ~[netty-codec-.Final.jar:.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:) ~[netty-codec-.Final.jar:.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:) [netty-transport-.Final.jar:.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:) [netty-transport-.Final.jar:.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:) [netty-transport-.Final.jar:.Final]
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:) [netty-transport-.Final.jar:.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:) [netty-transport-.Final.jar:.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:) [netty-transport-.Final.jar:.Final]
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:) [netty-transport-.Final.jar:.Final]
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:) [netty-transport-.Final.jar:.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:) [netty-transport-.Final.jar:.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:) [netty-transport-.Final.jar:.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:) [netty-transport-.Final.jar:.Final]
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:) [netty-transport-.Final.jar:.Final]
        at io.netty.util.concurrent.SingleThreadEventExecutor$.run(SingleThreadEventExecutor.java:) [netty-common-.Final.jar:.Final]
        at java.lang.Thread.run(Thread.java:) [?:1.8.0_131]
[--24T10::,][ERROR][c.f.s.h.SearchGuardHttpServerTransport] [node-] SSL Problem Received fatal alert: certificate_unknown
javax.net.ssl.SSLException: Received fatal alert: certificate_unknown
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:) ~[?:?]
        at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:) ~[?:?]
        at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:) ~[?:?]
        at sun.security.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:) ~[?:?]
        at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:) ~[?:?]
        at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:) ~[?:?]
        at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:) ~[?:?]
        at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:) ~[?:1.8.0_131]
        at io.netty.handler.ssl.SslHandler$SslEngineType$.unwrap(SslHandler.java:) ~[netty-handler-.Final.jar:.Final]
        at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:) ~[netty-handler-.Final.jar:.Final]
        at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:) ~[netty-handler-.Final.jar:.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:) ~[netty-codec-.Final.jar:.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:) ~[netty-codec-.Final.jar:.Final]
3、上文es的错误日志,显示es不知道证书(应该是客户端证书),但是已经配置了不做客户端认证,这又是为什么?
es部分配置
searchguard.ssl.http.clientauth_mode: NONE
总结
虽然logstash与es通信暂时没有成功,但是在尝试开通es权限的过程中,也积累了些经验和成果。
- 使用类似文中curl的方式(http请求),直接使用es服务。
 - 添加了Search Guard的es如何对外提供域名访问,实现后端多点服务/路由。
 
nginx可以处理来自外部的https请求,但目前不支持https代理,即nginx不能访问后端的https服务。如果仍然使用Search Guard,可以考虑使用四层负载均衡器lvs或者硬件负载均衡器,将请求透传给后端服务器;另外知乎文章上有推荐使用Squid。
参考
https://floragunn.com/
https://github.com/floragunncom/search-guard-docs
https://github.com/floragunncom/search-guard-docs/blob/master/installation.md
https://github.com/floragunncom/search-guard-docs/blob/master/tlsgeneratedemo_certificates.md
https://github.com/floragunncom/search-guard-ssl/tree/5.5.0
https://github.com/floragunncom/search-guard-docs/blob/master/kibana.md
https://github.com/floragunncom/search-guard-docs/blob/master/logstash.md
https://forum.nginx.org/read.php?2,15124,15256
https://www.zhihu.com/question/19871146
作者:蜂巢团队
来源:宜信技术学院
宜人贷蜂巢ELK Stack之elasticsearch权限探索的更多相关文章
- 宜人贷蜂巢API网关技术解密之Netty使用实践
		
一.背景 宜人贷蜂巢团队,由Michael创立于2013年,通过使用互联网科技手段助力金融生态和谐健康发展.自成立起一直致力于多维度数据闭环平台建设.目前团队规模超过百人,涵盖征信.电商.金融.社交. ...
 - ELK Stack总结
		
目录 ELK Stack 介绍 Elasticsearch 概念1(基础) CRUD基本用法 概念2(文本解析器) 查询 分析/聚合 概念3(架构原理的补充) Logstash基础 Kibana的数据 ...
 - ELK Stack 笔记
		
ELK Stack ELK Stack ELK Stack ELK 介绍 架构 Elasticsearch 安装 常见问题 关闭 Elasticsearch Elasticsearch-head Ki ...
 - 大数据日志分析产品——SaaS Cloud, e.g. Papertrail, Loggly, Sumo Logic;Open Source Frameworks, e.g. ELK stack, Graylog;Enterprise Products, e.g. TIBCO LogLogic, IBM QRadar, Splunk
		
Learn how you can maximize big data in the cloud with Apache Hadoop. Download this eBook now. Brough ...
 - ELK stack elasticsearch/logstash/kibana 关系和介绍
		
ELK stack elasticsearch 后续简称ES logstack 简称LS kibana 简称K 日志分析利器 elasticsearch 是索引集群系统 logstash 是日志归集集 ...
 - 快速搭建日志系统——ELK STACK
		
什么是ELK STACK ELK Stack是Elasticserach.Logstash.Kibana三种工具组合而成的一个日志解决方案.ELK可以将我们的系统日志.访问日志.运行日志.错误日志等进 ...
 - Elastic Stack之ElasticSearch分布式集群二进制方式部署
		
Elastic Stack之ElasticSearch分布式集群二进制方式部署 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 想必大家都知道ELK其实就是Elasticsearc ...
 - ELK Stack部署
		
部署ELK Stack 官网:https://www.elastic.co 环境准备: ip hostname 服务 用户.组 192.168.20.3 node2003 kibana6.5,file ...
 - ELK Stack 企业级日志收集平台
		
ELK Stack介绍 大型项目,多产品线的日志收集 ,分析平台 为什么用ELK? 1.开发人员排查问题,服务器上查看权限 2.项目多,服务器多,日志类型多 ELK 架构介绍 数据源--->lo ...
 
随机推荐
- ubuntu14.04  python + opencv 傻瓜式安装解决方案
			
ubuntu14.04 python + opencv 傻瓜式安装解决方案 ubuntu下使python和opencv来做开发的话,总要花那么点时间来配置环境.我偶然间发现了一种傻瓜式安装办法希望快 ...
 - 小程序语音红包开发中 汉字转拼音的问题  微信小程序红包开发遇到的坑
			
公司最近在开发微信小程序的红包功能,语音红包需要用到文字转拼音的功能. 之前介绍过怎么将中文的汉字转为拼音的,具体看下面这篇文章. 微信语音红包小程序开发如何提高精准度 红包小程序语音识别精准度 微信 ...
 - Oracle学习记录1
			
1.current_date与sysdate区别 在oracle中current_date与sysdate都是显示当前系统时间, 其结果基本相同,但是有三点区别:a. current_date返回的是 ...
 - 【Hihocoder1636】Pangu and Stones(区间DP)
			
题意:N堆石子,每次可以合并连续的长度从L到R的若干堆石子为1堆,费用为选择的石子总个数,求将N堆合并成1堆的最小总花费,无解输出0 思路:dp[i][j][k]表示将i到j这段区间合并为k堆的最小代 ...
 - 【kindeditor】KindEditor获取多个textarea文本框的值并判断非空
			
kindeditor官网:http://kindeditor.net/demo.php 如何获取多个KindEditor中textarea文本框的值,方式很多种(带有HTML标签). var intr ...
 - Method and apparatus for verification of coherence for shared cache components in a system verification environment
			
A method and apparatus for verification of coherence for shared cache components in a system verific ...
 - Django迁移数据库
			
我们已经编写了博客数据库模型的代码,但那还只是 Python 代码而已,Django 还没有把它翻译成数据库语言,因此实际上这些数据库表还没有真正的在数据库中创建 为了让 Django 完成翻译,创建 ...
 - [专题总结]数位DP
			
总结: 1:第i个数符合要求了,所以接下来的数都可以.如果没限制, 那么是有 10i-1 个.如果有限制,那么是 (nowx % 10i-1)+1 . 2:两种状态设置 有设状态d ...
 - github每次push提交都要输入账号密码
			
问题产生的原因是在克隆的时候使用的是https的方式或者用一些特殊的指令来克隆的github项目源,如 golang里的go get github.com/...... 没次提交push的时候都会提示 ...
 - HDU 1969 Pie【二分】
			
[分析] “虽然不是求什么最大的最小值(或者反过来)什么的……但还是可以用二分的,因为之前就做过一道小数型二分题(下面等会讲) 考虑二分面积,下界L=0,上界R=∑ni=1nπ∗ri2.对于一个中值x ...