如何移除AWS S3 Java客户端签名头中的Host及Endpoint信息?
解决方案
要移除签名头里的host和endpoint.com,可以通过自定义签名器或执行拦截器修改AWS SDK的签名逻辑,适配Ceph和代理场景。以下是针对AWS SDK Java v2.26.20的具体实现:
方法1:自定义签名器过滤签名头
import software.amazon.awssdk.auth.signer.Aws4Signer; import software.amazon.awssdk.auth.signer.params.Aws4SignerParams; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.signer.Signer; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import java.net.URI; import java.util.HashSet; import java.util.Set; public class CustomS3Client { public static S3Client createS3Client(String accessKey, String secretKey, String endpoint) { // 自定义签名器,移除不需要参与签名的头 Signer customSigner = new Aws4Signer() { @Override public void sign(SignRequest request, Aws4SignerParams params) { Set<String> filteredHeaders = new HashSet<>(request.signedHeaders()); filteredHeaders.remove("host"); filteredHeaders.remove("endpoint.com"); SignRequest filteredRequest = SignRequest.builder() .from(request) .signedHeaders(filteredHeaders) .build(); super.sign(filteredRequest, params); } }; AwsBasicCredentials credentials = AwsBasicCredentials.create(accessKey, secretKey); return S3Client.builder() .endpointOverride(URI.create(endpoint)) .credentialsProvider(StaticCredentialsProvider.create(credentials)) .serviceConfiguration(srvcConf -> srvcConf.pathStyleAccessEnabled()) .region(Region.US_EAST_1) .overrideConfiguration(ClientOverrideConfiguration.builder() .signer(customSigner) .build()) .build(); } }
方法2:用执行拦截器修改签名头
如果自定义签名器过于复杂,也可以通过拦截器在签名前调整头集合:
import software.amazon.awssdk.core.interceptor.Context; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import java.net.URI; import java.util.HashSet; import java.util.Set; // 定义拦截器 ExecutionInterceptor headerFilterInterceptor = new ExecutionInterceptor() { @Override public void beforeSigning(Context.BeforeSigning context, ExecutionAttributes executionAttributes) { SignRequest originalRequest = context.signRequest(); Set<String> updatedHeaders = new HashSet<>(originalRequest.signedHeaders()); updatedHeaders.remove("host"); updatedHeaders.remove("endpoint.com"); SignRequest updatedRequest = SignRequest.builder() .from(originalRequest) .signedHeaders(updatedHeaders) .build(); context.modifySignRequest(updatedRequest); } }; // 构建客户端时添加拦截器 AwsBasicCredentials credentials = AwsBasicCredentials.create(accessKey, secretKey); S3Client client = S3Client.builder() .endpointOverride(new URI("https://endpoint.com")) .credentialsProvider(StaticCredentialsProvider.create(credentials)) .serviceConfiguration(srvcConf -> srvcConf.pathStyleAccessEnabled()) .region(Region.US_EAST_1) .overrideConfiguration(ClientOverrideConfiguration.builder() .addExecutionInterceptor(headerFilterInterceptor) .build()) .build();
说明
- 两种方法都是通过修改签名前的
SignRequest头集合,移除不参与签名的字段,避免代理修改头后导致签名失效。 - 配置完成后,测试客户端与Ceph的交互,确保签名逻辑符合Ceph的验证要求。
内容的提问来源于stack exchange,提问作者Prostakov Alexey
相关产品推荐
相关产品推荐

