我正在尝试使用Transfer Manager从AWS S3将文件从特定于用户的文件夹下载到我的iOS移动应用程序,如下所示:
@IBAction func download() {
let transferManager = AWSS3TransferManager.default()!
let downloadingFileURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("disney1.jpg")
let downloadRequest = AWSS3TransferManagerDownloadRequest()!
downloadRequest.bucket = "sidestreamx"
// user's UUID/disney1
downloadRequest.key = "631d121f-b294-4318-b3cd-36b3b74ebdff/disney1"
downloadRequest.downloadingFileURL = downloadingFileURL
transferManager.download(downloadRequest).continue(with: AWSExecutor.mainThread(), with: {
(task: AWSTask<AnyObject>) -> Any? in
if let error = task.error as? NSError {
// handle error
return nil
}
self.imageView.image = UIImage(contentsOfFile: downloadingFileURL.path)
return nil
})
}
我的IAM角色权限政策如下,来自this AWS doc:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "GetBucketListIfRequestIsForUser",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::sidestreamx"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"${cognito-identity.amazonaws.com:sub}/*"
]
}
}
},
{
"Sid": "S3GetObjects",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::sidestreamx/${cognito-identity.amazonaws.com:sub}/*"
]
}
]
}
我得到的回应是
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>E1F205B58EF4A670</RequestId>
<HostId>dUWI8PfVZL3mJmykjhXRqvFd1yt/CqDFNlwgwD3kmLk2vrMBP6JvVgezMYSROt3KyE3dx0+3eDE=</HostId>
</Error>
用户通过AWS Cognito User Pool&amp; Cognito联合身份。我调试并解压缩了JWT令牌,并看到了sub = "631d121f-b294-4318-b3cd-36b3b74ebdff"
。我甚至使用Charles来查看请求/响应。
确实有效我将${cognito-identity.amazonaws.com:sub}
替换为S3GetObjects
631d121f-b294-4318-b3cd-36b3b74ebdff
arn:aws:s3:::sidestreamx/631d121f-b294-4318-b3cd-36b3b74ebdff/*
以获取 bullet[i][1] -= 10;
。第一个语句可以继续使用策略变量,它仍然有效。如果我完全删除第一个语句,它就会起作用!当我将策略变量添加到它开始崩溃的最后一个语句时。
我已查看此Stack Overflow个问题和this one,但无济于事。所以,是的,我不知道。我已经花了将近9个工时,所以任何帮助都会真诚地受到赞赏。
答案 0 :(得分:6)
问题解决了。事实证明,${cognito-identity.amazonaws.com:sub}
并未真正引用JWT令牌中的sub
。它引用credentialsProvider中的IdentityID:
(AWSServiceManager.default().defaultServiceConfiguration.credentialsProvider
as! AWSCognitoCredentialsProvider).getIdentityId()
.continue({task -> Any? in
print("Credentials ID is \(task.result!)")
return nil
})
我手动在我的存储桶中创建了一个文件夹,其名称等于task.result!
(格式为us-east-1:XXXXXXXXXXXXXXXXXX
fyi),并且有效。