SpringBoot_minio sdk使用自签名https证书错误处理

1.问题描述

minio 8.4.4 使用自签名的https的api连接会报错证书错误

1.1 报错日志

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

1.2 maven 依赖配置

        <!--minio java sdk-->
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>8.4.4</version>
            <exclusions>
                <exclusion>
                    <groupId>com.squareup.okhttp3</groupId>
                    <artifactId>okhttp</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.10.0</version>
        </dependency>

1.3 当前spring MinioClient配置

@Configuration
@EnableConfigurationProperties(MinioProperties.class)
public class MinioConfig {
    @Bean
    public MinioClient minioClient(MinioProperties properties){
        properties.check();
        return MinioClient.builder()
                .endpoint(properties.getEndpoint())
                .credentials(properties.getAccessKey(), properties.getSecretKey())
                .build();

    }
}

2.问题分析

通常是因为MinIO默认情况下会验证服务器的TLS证书。在生产环境中,使用自签名证书并不推荐,因为它们不受信任的证书颁发机构(CA)签署,可能会导致安全问题。

3.问题解决

3.1 使用受信任的证书

为了在生产环境中确保安全性,建议获取一个受信任的SSL证书,可以从证书颁发机构(CA)购买,或者使用免费的证书颁发机构(例如Let’s Encrypt)获取SSL证书。

3.2 忽略证书验证

3.2.1 minio客户端

在MinIO客户端(例如mc命令行工具)中,可以使用–insecure选项来忽略证书验证。例如:

mc --insecure <command>

这会告诉MinIO客户端不要验证服务器的TLS证书。请注意,这种做法会降低安全性,不建议在生产环境中使用。

3.2.2 minio sdk 忽略证书验证

在使用Java SDK与自签名证书的服务器进行通信时,一般可以通过自定义SSLContext来忽略证书验证。

MinIO的Java SDK(version 8.0.6及以上)允许自定义OkHttpClient,我们可以使用httpClient方法传递一个自定义的OkHttpClient实例。以便在HTTP、正常HTTPS和自签名HTTPS之间实现兼容性

下面是如何使用自定义的OkHttpClient实现对HTTP、正常HTTPS和自签名HTTPS的兼容性

@Configuration
@EnableConfigurationProperties(MinioProperties.class)
public class MinioConfig {
    private static final Logger LOGGER = LoggerFactory.getLogger(MinioConfig.class);

    @Bean
    public MinioClient minioClient(MinioProperties properties){
        properties.check();

        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] {
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[0];
                    }

                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
                        // Do nothing (trust any client certificate)
                    }

                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
                        // Do nothing (trust any server certificate)
                    }
                }
        };

        // Install the all-trusting trust manager
        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
        } catch (Exception e) {
            LOGGER.error("Install the all-trusting trust manager error:{}", e.getMessage());
        }


        // Create a custom OkHttpClient that trusts all certificates
        OkHttpClient customHttpClient = new OkHttpClient.Builder()
                .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0])
                .hostnameVerifier((hostname, session) -> true)
                .build();

        // Set the custom SSLContext for MinioClient
        return MinioClient.builder()
                .endpoint(properties.getEndpoint())
                .credentials(properties.getAccessKey(), properties.getSecretKey())
                .httpClient(customHttpClient)
                .build();

    }


}

  1. 在上面的代码中,我们创建了一个SSLContext,其中的X509TrustManager会信任所有证书,无论其是否由信任的证书颁发机构(CA)签署。
  2. 创建了一个自定义的OkHttpClient,该客户端信任所有证书。然后,我们使用MinioClient.builder()方法,将自定义的OkHttpClient传递给httpClient()方法

这种方法会将所有证书都视为受信任的,因此请仅在非生产环境中使用此方法,以确保通信的安全性和完整性。在生产环境中,建议使用受信任的SSL证书。

3.2.2.1 拓展: 补充minioclient请求日志

之前minioclient与服务器端交互使用默认的httpclient的客户端,请求没有打印详细日志. 既然上面自定义自己的httpclient那么可以补充自定义拦截器打印日志

public class CustomLoggingInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        
        long startTime = System.nanoTime();
        System.out.println("Sending request " + request.url() + " on " + chain.connection() + "\n" + request.headers());

        Response response = chain.proceed(request);
        
        long endTime = System.nanoTime();
        System.out.println("Received response for " + response.request().url() + " in " + ((endTime - startTime) / 1e6) + "ms\n" + response.headers());

        MediaType contentType = response.body().contentType();
        String content = response.body().string();
        System.out.println("Response body:\n" + content);

        ResponseBody wrappedBody = ResponseBody.create(contentType, content);
        return response.newBuilder().body(wrappedBody).build();
    }
}

修改MinioConfig增加okhttp拦截器

        // Create a custom OkHttpClient that trusts all certificates
        OkHttpClient customHttpClient = new OkHttpClient.Builder()
                .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0])
                .hostnameVerifier((hostname, session) -> true)
                .addInterceptor(new CustomLoggingInterceptor()) // Add custom interceptor here
                .build();

效果
在这里插入图片描述

4. 问题总结

minio客户端本质使用httpclient与服务端交互,因此证书问题处理其实只是httpclient对证书的兼容处理。该处理方式可以运用到其他使用到httpclient的场景。

5.附录

代码优化

@Configuration
@EnableConfigurationProperties(MinioProperties.class)
public class MinioConfig {
    private static final Logger LOGGER = LoggerFactory.getLogger(MinioConfig.class);

    @Bean
    public MinioClient minioClient(MinioProperties properties){
        properties.check();

        OkHttpClient customHttpClient = null;
        if (properties.getEndpoint().startsWith("https://")) {
            // 如果是HTTPS,使用自定义的OkHttpClient处理自签名的HTTPS请求
            customHttpClient = createCustomOkHttpClient();
        }

        MinioClient minioClient;
        if (customHttpClient != null) {
            // 如果使用了自定义的OkHttpClient
            minioClient = MinioClient.builder()
                    .endpoint(properties.getEndpoint())
                    .credentials(properties.getAccessKey(), properties.getSecretKey())
                    .httpClient(customHttpClient)
                    .build();

        } else {
            // 如果是普通HTTP,使用默认的OkHttpClient
            minioClient = MinioClient.builder()
                    .endpoint(properties.getEndpoint())
                    .credentials(properties.getAccessKey(), properties.getSecretKey())
                    .build();

        }
        return minioClient;
    }

    /**
     * Set the custom SSLContext for MinioClient
     * @return
     */
    private static OkHttpClient createCustomOkHttpClient() {
        // 创建自定义的OkHttpClient,用于处理自签名的HTTPS请求

        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] {
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[0];
                    }

                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
                        // Do nothing (trust any client certificate)
                    }

                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
                        // Do nothing (trust any server certificate)
                    }
                }
        };

        // Install the all-trusting trust manager
        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
        } catch (Exception e) {
            LOGGER.error("Install the all-trusting trust manager error:{}", e.getMessage());
        }


        // Create a custom OkHttpClient that trusts all certificates
        OkHttpClient customHttpClient = new OkHttpClient.Builder()
                .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0])
                .hostnameVerifier((hostname, session) -> true)
                // 增加minio http请求日志打印
                //.addInterceptor(new CustomLoggingInterceptor()) // Add custom interceptor here
                .build();
        return customHttpClient;
    }


}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
springboot集成minio使用步骤如下: 1. 配置文件桶权限:可以在配置文件中设置minio的桶权限,包括读、写、删除等操作。可以根据具体需求进行配置。 2. 引入minio客户端依赖:在项目的pom.xml文件中添加minio客户端的依赖,以便在项目中使用minio的功能。 3. 配置文件修改:在项目的配置文件中添加minio的相关配置,包括minio服务器的地址、端口、用户名、密码等信息。 4. 定义minio配置类:创建一个配置类,用于将配置文件中的minio配置属性注入到该类中,方便后续使用。 5. 封装MinioClient:使用创建的minio配置类,创建一个MinioClient对象,用于与minio服务器进行交互。 6. HTTP接口实例:根据业务需求,编写相应的HTTP接口,使用MinioClient对象进行minio的相关操作,如上传文件、下载文件、创建桶等。 7. 总结:根据项目的具体情况,总结集成minio使用体验和效果,并进行必要的优化和调整。 以上是springboot集成minio的基本步骤和流程,通过配置文件和代码的配合,可以实现对minio的灵活使用。可以根据具体的需求进行相应的扩展和定制。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [springboot集成minio客户端](https://blog.csdn.net/water1209/article/details/124241782)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [springboot集成Minio](https://blog.csdn.net/AYANBAO/article/details/130031830)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值