0

我如何使用静态凭据(访问密钥和秘密访问密钥)使用 swift 从 iOS 应用程序将文件上传到 s3 存储桶。我已经尝试了放大指南,但我无法生成 json 文件,当我尝试配置它时出现此错误

UnrecognizedClientException:请求中包含的安全令牌无效。

但是我可以使用 bash 脚本(curl)上传文件,当我尝试复制相同的文件时,我看到以下错误,我现在可以使用下面的方法而不是使用 AWS 放大库来实现,无论哪个有效第一的

我们计算的请求签名与您提供的签名不匹配。检查您的 AWS 秘密访问密钥和签名方法。有关详细信息,请参阅 REST 身份验证和 SOAP 身份验证了解详细信息。

下面是工作 bash 脚本,

file_to_upload=card.jpg
bucket=dash-poc
filepath="/${bucket}/${file_to_upload}"
contentType="image/jpeg"
dateValue=`date -R`
signature_string="PUT\n\n${contentType}\n${dateValue}\n${filepath}"
signature_hash=`echo -en ${signature_string} | openssl sha1 -hmac ${s3_secret_key} -binary | base64`
# actual curl command to do PUT operation on s3
echo $signature_hash
curl -v -X PUT -T "${file_to_upload}" \
  -H "Host: *********.com" \
  -H "Date: ${dateValue}" \
  -H "Content-Type: ${contentType}" \
  -H "Authorization: AWS ${s3_access_key}:${signature_hash}" \
  https://**********.com/dash-poc/card.jpg

编辑:用于 v4 签名

 func signS3RequestV4(urlRequest : NSMutableURLRequest, credentials: AWSCredentials) -> String{
    let awsEndpoint = AWSEndpoint(region: .EUWest2, serviceName: "s3", url: URL(string: "******.com/")!)

            urlRequest.setValue(awsEndpoint!.hostName, forHTTPHeaderField: "host")
            
            let date = Date()
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = AWSDateISO8601DateFormat2
            dateFormatter.timeZone = TimeZone(identifier: "UTC")
            let dateStamp = dateFormatter.string(from: date)
            urlRequest.setValue(dateStamp, forHTTPHeaderField: "x-amz-date")
            
            let dateFormatterShort = DateFormatter()
            dateFormatterShort.dateFormat = AWSDateShortDateFormat1
            let dateStampShort = dateFormatterShort.string(from: date)
        
            let scope = String(format: "%@/%@/%@/%@", dateStampShort, awsEndpoint!.regionName, (awsEndpoint?.serviceName)!, AWSSignatureV4Terminator)
            let signingCredentials = String(format: "%@/%@", credentials.accessKey, scope)
            
            let httpMethod = urlRequest.httpMethod
            let path = urlRequest.url!.path
            let query = urlRequest.url?.query ?? ""
            
            let contentSha256 = AWSSignatureSignerUtility.hexEncode(String(data: AWSSignatureSignerUtility.hash(urlRequest.httpBody), encoding: String.Encoding.ascii))
            urlRequest.setValue(contentSha256, forHTTPHeaderField: "x-amz-content-sha256")
            
            let headers = urlRequest.allHTTPHeaderFields
            let canonicalRequest = AWSSignatureV4Signer.getCanonicalizedRequest(httpMethod, path: path, query: query, headers: headers, contentSha256: contentSha256)
            
            let stringToSign = String(format: "%@\n%@\n%@\n%@",
                                      AWSSignatureV4Algorithm,
                                      urlRequest.value(forHTTPHeaderField: "x-amz-date")!,
                                      scope, AWSSignatureSignerUtility.hexEncode(AWSSignatureSignerUtility.hashString(canonicalRequest)))
            print("AWS4 String to Sign \(stringToSign)")
            
            let kSigning = AWSSignatureV4Signer.getV4DerivedKey(credentials.secretKey, date: dateStampShort, region: awsEndpoint?.regionName, service: awsEndpoint?.serviceName)
            
            let signature = AWSSignatureSignerUtility.sha256HMac(with: stringToSign.data(using: String.Encoding.utf8), withKey: kSigning)
        let signatureString = AWSSignatureSignerUtility.hexEncode(String(data: signature, encoding: String.Encoding.ascii))
            let authorization = String(format: "%@ Credential=%@, SignedHeaders=%@, Signature=%@",
                AWSSignatureV4Algorithm,
                signingCredentials,
                AWSSignatureV4Signer.getSignedHeadersString(headers), signatureString)
            
            return authorization
        }

请指导我完成此操作,任何帮助将不胜感激。

4

0 回答 0