MinIO最新版使用的是certgen工具,先下载这个工具certgen
(用的是Windows版的)
2、生成证书调用cmd命令,运行certgen,要注意要把自己电脑的ip地址(本地调试)以及部署服务器的ip地址添加进去
.certgen-windows-amd64.exe -host "ip1,ip2"
参数:
-client
whether this cert is a client certificate
-duration duration
Duration that certificate is valid for (default 8760h0m0s)
-ecdsa-curve string
ECDSA curve to use to generate a key. Valid values are P224, P256 (recommended), P384, P521 (default "P256")
-ed25519
Generate an Ed25519 key
-host string
Comma-separated hostnames and IPs to generate a certificate for
-no-ca
whether this cert should not be its own Certificate Authority
-org-name string
Organization name used when generating the certs (default "Certgen Development")
-start-date string
Creation date formatted as Jan 1 15:04:05 2011
参数说明:(个人理解)
-duration 代表证书的过期时间,默认的8760个小时正好是十年(3650*24=8760)
-host 应该是必填项,表示为哪个ip地址生成证书。
-no-ca 是否有ca, 我用的参数是no
-org-name 表示组织名称
-start-date 起始时间,参数是字符串。目前不知道是什么格式的字符串。
3 部署证书运行命令后,会在当前目录产生两个文件,public.crt和private.key,将这两个文件拷贝到
- Linux: ${HOME}/.minio/certs
- Windows: %%USERPROFILE%%.miniocerts
重启MinIO服务
*** 注意***
MinIO官网的命令是
./certgen -ca -host "10.10.0.3,10.10.0.4,10.10.0.5"
但是会报错,产生的原因是参数不对,应该是版本的问题,
目前的策略是对于 -ca 采取默认的方法,等有时间再详细研究。
4 Java调用MinIO客户端 4.1 region的坑主要是阐述我所遇到的问题,问题如下。
该代码的功能是连接客户端,然后调用方法生成文件的临时下载链接。
@SneakyThrows
public static void main(String[] args) {
MinioClient client = MinioClient.builder()
.endpoint("https://IP:PORT")
.credentials("USERNAME", "PASSWORD")
.build();
String url = client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket("file")
.object("00c7facb-da6c-4df1-8821-907f2b39c9cd.pdf")
.expiry(60 * 60 * 24)
.build());
System.out.println(url);
}
运行的时候报错的提示信息如下。
Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1946) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:316) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:310) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1639) at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223) at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1037) at sun.security.ssl.Handshaker.process_record(Handshaker.java:965) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379) at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:379) at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:337) at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:209) at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226) at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106) at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74) at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255) at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201) at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154) at io.minio.S3Base.execute(S3Base.java:507) at io.minio.S3Base.getRegion(S3Base.java:669) at io.minio.MinioClient.getPresignedObjectUrl(MinioClient.java:717) at cn.ac.iie.MinIoTest.main(MinIoTest.java:35) Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:397) at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302) at sun.security.validator.Validator.validate(Validator.java:262) at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324) at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229) at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1621) ... 28 more Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141) at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280) at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:392) ... 34 more
能够保证用户名密码正确,资源也是存在的,研究错误提示信息显示滋以为是SSL的问题,百度了一下解决方案,均不能解决我的问题。
尝试过多种解决方式。
(1)尝试过调用客户端的 httpClient(new OkHttpClient())方法,跳过安全检查。结果不行。
(2)以为是证书的问题,也重新生成过证书。结果不行。通过浏览器直接访问图形化界面操作是没有问题的,说明不是证书的问题。
(3)配置过代码里加载证书,通过
Provider provider = new MinioClientConfigProvider("public.crt", "minio");还是不行。
守得云开见月明,最后还是通过debug,一次一次的尝试,发现是有个参数需要配置。
String url = client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.region("region") ###这里!这里!
.bucket("file")
.object("00c7facb-da6c-4df1-8821-907f2b39c9cd.pdf")
.expiry(60 * 60 * 24)
.build());
System.out.println(url);
该参数的作用是描述的是服务器的物理位置,默认是us-east-1(美国东区1),这也是亚马逊S3的默认区域。
疑惑的是,该方法的形参可以是任意值即可使用,不必和MinIO的参数配置相同。



