package com.ard.sample.storage.service.impl; import com.ard.common.config.OssConfiguration; import com.ard.oss.model.CredentialsDTO; import com.ard.sample.component.mqtt.model.*; import com.ard.sample.component.mqtt.service.IMessageSenderService; import com.ard.oss.model.StsCredentialsDTO; import com.ard.sample.config.DockConfiguration; import com.ard.sample.storage.service.IStorageService; import com.ard.oss.service.impl.OssServiceContext; import io.minio.MinioClient; import io.minio.PutObjectArgs; import io.minio.credentials.StaticProvider; import io.minio.errors.MinioException; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.integration.annotation.ServiceActivator; import org.springframework.integration.mqtt.support.MqttHeaders; import org.springframework.messaging.MessageHeaders; import org.springframework.stereotype.Service; import java.io.ByteArrayInputStream; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; /** * @author sean * @version 0.3 * @date 2022/3/9 */ @Slf4j @Service public class StorageServiceImpl implements IStorageService { @Autowired private IMessageSenderService messageSender; @Autowired private OssServiceContext ossService; @Override public StsCredentialsDTO getSTSCredentials() { CredentialsDTO credentials = ossService.getCredentials(); //验证一下minio的临时凭证是否可用 log.info("验证临时凭证是否有效:{}", credentials); execMinio(DockConfiguration.endpoint, credentials.getAccessKeyId(), credentials.getAccessKeySecret(), credentials.getSecurityToken(), DockConfiguration.bucket, "test_object"); return StsCredentialsDTO.builder() //机场媒体库minio配置信息用代理地址,桶用机场的桶。 //.endpoint(OssConfiguration.endpoint) .endpoint(DockConfiguration.endpoint) // .bucket(OssConfiguration.bucket) .bucket(DockConfiguration.bucket) // .credentials(ossService.getCredentials()) .credentials(credentials) .provider(OssConfiguration.provider) .objectKeyPrefix(OssConfiguration.objectDirPrefix) .region(OssConfiguration.region) .build(); } @Override @ServiceActivator(inputChannel = ChannelName.INBOUND_REQUESTS_STORAGE_CONFIG_GET, outputChannel = ChannelName.OUTBOUND) public void replyConfigGet(CommonTopicReceiver receiver, MessageHeaders headers) { // 20251219 这里是获取上传临时凭证的接口,稍候分析下是否满足条件,如果可以的话就直接回复临时凭证即可 CommonTopicResponse response = CommonTopicResponse.builder() .tid(receiver.getTid()) .bid(receiver.getBid()) .data(RequestsReply.success(this.getSTSCredentials())) .timestamp(System.currentTimeMillis()) .method(RequestsMethodEnum.STORAGE_CONFIG_GET.getMethod()) .build(); messageSender.publish(headers.get(MqttHeaders.RECEIVED_TOPIC) + TopicConst._REPLY_SUF, response); } // 验证一下临时凭证是否可用 public void execMinio(String endpoint, String accessKeyId, String accessKeySecret, String securityToken, String bucketName, String testObjectName) { // 1. 替换为你要验证的临时凭证参数(从 getCredentials() 返回的结果中复制) try { // 2. 用临时凭证(含 securityToken)初始化 MinIO 客户端 MinioClient minioClient = MinioClient.builder() .endpoint(endpoint) // .credentials(accessKeyId, accessKeySecret) // 核心:传入 securityToken .credentialsProvider(new StaticProvider(accessKeyId, accessKeySecret, securityToken)) .region("us-east-1") // 和你配置的 region 一致 .build(); // 3. 执行验证操作:上传一个测试文件(模拟机场上传媒体文件) String testContent = "Test securityToken validity"; minioClient.putObject( PutObjectArgs.builder() .bucket(bucketName) .object(testObjectName) .stream( new ByteArrayInputStream(testContent.getBytes()), testContent.getBytes().length, -1 ) .build() ); // 4. 验证成功:无异常则 Token 有效 log.info("✅ securityToken 验证成功!临时凭证可正常操作 MinIO"); // (可选)额外验证:列出桶内文件,确认上传成功 log.info("📌 验证文件已上传至:" + bucketName + "/" + testObjectName); } catch (MinioException e) { // 5. 验证失败:捕获 MinIO 异常,打印具体原因 log.error("❌ securityToken 验证失败!MinIO 错误:" + e.getMessage()); // System.err.println("错误代码:" + e.errorCode()); } catch (InvalidKeyException | NoSuchAlgorithmException e) { log.error("❌ 凭证签名错误:" + e.getMessage()); } catch (Exception e) { log.error("❌ 验证过程异常:" + e.getMessage()); } } }