0

我正在为 Amazon S3 服务工作,并且我已将 jets3t 用于 API。其实很久以前我上次使用的jets3t版本是:0.8.1,现在新的jets3t版本是:0.9.6。我正在使用 Java 7。

我正在尝试与 S3 连接,但对于少数存储桶(如法兰克福),它会引发以下问题: 不支持您提供的授权机制。请使用 AWS4-HMAC-SHA256

我分析了新jets3t所做的更改,并想合并到我现有的旧代码中,目前我无法完全更改jets3t的代码,我只想解决授权问题。

因此,我更新了authorizeHttpRequest请求方法,其中包含最新的 github 更改,如下所示:https ://github.com/mondain/jets3t/tree/master/jets3t :

public void authorizeHttpRequest(HttpMethod httpMethod, String forceRequestSignatureVersion) throws Exception {
        if (getProviderCredentials() != null) {
            if (log.isDebugEnabled()) {
                log.debug("Adding authorization for Access Key '"
                        + getProviderCredentials().getAccessKey() + "'.");
            }
        } else {
            if (log.isDebugEnabled()) {
                log.debug("Service has no Credential and is un-authenticated, skipping authorization");
            }
            return;
        }
// Clear any existing Authorization headers
        httpMethod.removeRequestHeader("Authorization");

        // Set/update the date timestamp to the current time
        // Note that this will be over-ridden if an "x-amz-date" or
        // "x-goog-date" header is present.
        httpMethod.setRequestHeader("Date",
                ServiceUtils.formatRfc822Date(getCurrentTimeWithOffset()));

        URI requestURI = null;
        if (httpMethod.getURI().isAbsoluteURI()) {
            requestURI = httpMethod.getURI();
        }
//        else {
//            // Handle strange edge-case that can occur when retrying requests in
//            // which the URI object has a null host value, re #205
//            try {
//                // Re-create request's URI to populate its internal host value
//                requestURI = new java.net.URI(String.format("%s%s",
//                        context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST).toString(), httpMethod.getURI()));
//            } catch (URISyntaxException e) {
//                throw new ServiceException(
//                    "Failed to re-create URI for reHttpCoreContextquest containing a URI"
//                    + " object with an invalid null Host value", e);
//            }
//        }
        //String forceRequestSignatureVersion = null;

        String requestBucketName = ServiceUtils.findBucketNameInHostOrPath(
                new java.net.URI(requestURI.toString()), this.getEndpoint());
        String requestSignatureVersion = this.getJetS3tProperties()
                .getStringProperty(
                "storage-service.request-signature-version", "AWS2")
                .toUpperCase();

        if ("AWS4-HMAC-SHA256".equalsIgnoreCase(forceRequestSignatureVersion)
                || "AWS4-HMAC-SHA256".equalsIgnoreCase(requestSignatureVersion)
                // If we have a cached region for request's bucket target, we know
                // we have used "AWS4-HMAC-SHA256" for this bucket in the past.
                || (this.regionEndpointCache != null
                && this.regionEndpointCache.containsRegionForBucketName(
                requestBucketName))) {
            requestSignatureVersion = "AWS4-HMAC-SHA256";
            // Look up AWS region appropriate for the request's Host endpoint
            // from the request's Host if a definite mapping is available...
            String region = SignatureUtils.awsRegionForRequest(new java.net.URI(requestURI.toString()));
            if (region != null) {
                // Try caching the definitive region in case this request is
                // directed at a bucket. If it's not a bucket-related request
                // this is a no-op.
                this.regionEndpointCache.putRegionForBucketName(
                        requestBucketName, region);
            }
            // ...otherwise from the region cache if available...
            if (region == null && this.regionEndpointCache != null) {
                region = this.regionEndpointCache.getRegionForBucketName(
                        requestBucketName);

                // We cached a bucket-to-region mapping previously but this
                // request doesn't use the correct Host name for the region,
                // so fix that now to avoid failure or excess retries.
                java.net.URI newURI = new java.net.URI(requestURI.toString());
                org.apache.commons.httpclient.URI apacheURI = new org.apache.commons.httpclient.URI(SignatureUtils.awsV4CorrectHostnameForRegion(
                        newURI, region).toString());
                if (region != null) {
                    (httpMethod).setURI(apacheURI);
                }
            }
            // ...finally fall back to the default region and hope for the best.
            if (region == null) {
                region = "us-east-1";
            }


            String requestPayloadHexSHA256Hash =
                    SignatureUtils.awsV4GetOrCalculatePayloadHash(httpMethod);
            httpMethod.setRequestHeader(
                    "x-amz-content-sha256", requestPayloadHexSHA256Hash);

            SignatureUtils.awsV4SignRequestAuthorizationHeader(
                    requestSignatureVersion, httpMethod,
                    this.getProviderCredentials(), requestPayloadHexSHA256Hash,
                    region);
        } else if ("AWS2".equalsIgnoreCase(forceRequestSignatureVersion)
                || "AWS2".equalsIgnoreCase(requestSignatureVersion)) {
            /*
             * Determine the complete URL for the S3 resource, including any S3-specific parameters.
             */
            // Use raw-path, otherwise escaped characters are unescaped and a wrong
            // signature is produced
            String fullUrl = requestURI.getURI();

            // If bucket name is not already part of the full path, add it.
            // This can be the case if the Host name has a bucket-name prefix,
            // or if the Host name constitutes the bucket name for DNS-redirects.
            String bucketName = ServiceUtils.findBucketNameInHostOrPath(
                    new java.net.URI(requestURI.toString()), getEndpoint());
            if (bucketName != null && requestURI.getHost().startsWith(bucketName)) {
                fullUrl = "/" + bucketName + fullUrl;
            }

            String queryString = new java.net.URI(requestURI.toString()).getRawQuery();
            if (queryString != null && queryString.length() > 0) {
                fullUrl += "?" + queryString;
            }

            // Generate a canonical string representing the operation.
            String canonicalString = RestUtils.makeServiceCanonicalString(
                    httpMethod.getName(),
                    fullUrl,
                    convertHeadersToMap(httpMethod.getRequestHeaders()),
                    null,
                    getRestHeaderPrefix(),
                    getResourceParameterNames());
            if (log.isDebugEnabled()) {
                log.debug("Canonical string ('|' is a newline): " + canonicalString.replace('\n', '|'));
            }

            // Sign the canonical string.
            String signedCanonical = ServiceUtils.signWithHmacSha1(
                    getProviderCredentials().getSecretKey(), canonicalString);

            // Add encoded authorization to connection as HTTP Authorization header.
            String authorizationString = getSignatureIdentifier() + " "
                    + getProviderCredentials().getAccessKey() + ":" + signedCanonical;
            httpMethod.setRequestHeader("Authorization", authorizationString);
        } else {
            throw new ServiceException("Unsupported property setting for "
                    + "storage-service.request-signature-version \""
                    + requestSignatureVersion + "\", must be one of: "
                    + "\"AWS2\" (legacy), \"AWS4-HMAC-SHA256\"");
        }
    }

但是现在它抛出了新的问题:我们计算的请求签名与您提供的签名不匹配。检查您的密钥和签名方法。

如何解决 jets3t 的身份验证问题?也有 AWS SDK 的选项,但是如果我使用 AWS SDK 进行身份验证,两者如何一起管理?

4

1 回答 1

0

添加以下您的 AWS 设置:

AWS_S3_SIGNATURE_VERSION = 's3v4' AWS_S3_REGION_NAME = 'eu-west-3' # 输入您的 REGION_NAME... 您可以在您的存储桶 AWS 规范中找到它。

由于 AWS 向新存储桶添加了签名要求,版本变量允许将其设置为 v4。至于 Region 变量。我注意到有人报告说,在某些地区(如印度)它有所作为……以防万一。

于 2021-05-18T15:43:21.440 回答