Cognito:从浏览器将文件上传到 S3 到自定义用户子文件夹中



这是一部分问题,一部分回答了我挣扎的一些问题。 问题在底部。

我想使用 Cognito 直接从浏览器上传文件到 S3。它适用于未经身份验证的用户,但随后每个用户都可以访问同一存储桶或至少相同的文件夹。我希望每个用户只能访问他们的文件夹。

经过 3 天的头部撞击,我能够让 Cognito 在一个紧凑的 php 文件中使用 JavaScript 和 PHP 使用自定义开发人员身份验证身份。

在服务器上,我使用getOpenIdTokenForDeveloperIdentity接收用户名johnsmithIdentityIdToken

然后,我立即向客户端提供 id 和令牌以对其进行身份验证并将文件上传到 S3:

<!-- BEGIN SERVER SIDE -->
<?php
session_start();
//Include AWS client libs
require ('vendor/autoload.php');
use AwsCognitoIdentityCognitoIdentityClient;
use AwsStsStsClient;
/* Global Vars */
$aws_region = 'us-east-1';
$aws_key = 'JF4L3ELC4CAVQV4VAKIA';
$aws_secret = 'OKfoWZ91qZHBhIBzDZLINzHVs9Ymaxi689Ym3vT8';
$identity_pool_id = 'us-east-1:83024a7c-438e-aa29-8bac-ff6717d73ec5';
//Initialize a Cognito Identity Client using the Factory
$client = CognitoIdentityClient::factory(array('region' => $aws_region, 'key' => $aws_key, 'secret' => $aws_secret));
/* Acquire new Identity */
$identity = $client->getOpenIdTokenForDeveloperIdentity(array('IdentityPoolId' => $identity_pool_id, 'Logins' => array('my-custom-login' => 'johnsmith')));
//Obtain Identity from response data structure
$id = $identity->get('IdentityId');
$token = $identity->get('Token');
print_r($identity);
// Results in:
// [IdentityId] => us-east-1:c4db3eca-6ed0-af08-4aaa-a33aee2e994a
// [Token] => eyJraWQiOiJ1cy1lYXN0LTExIiwidHlwIjoiSldTIiwiYWxnIjoiUlM1MTIifQ.eyJzd...
?>
<!-- BEGIN CLIENT SIDE -->
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.436.0.min.js"></script>
<script>
var bucketName = 'mybucket';
//Get CognitoIdentityCredentials
AWS.config.region = 'us-east-1';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityId: '<?php echo $id; ?>',
IdentityPoolId: '<?php echo $identity_pool_id; ?>',
Logins: {
//'my-custom-login':'johnsmith', //This does not work. It throws Error 400: Please provide a valid public provider.
'cognito-identity.amazonaws.com':'<?php echo $token; ?>'
}
});
//S3 Upload
var s3 = new AWS.S3({
//region: 'us-east-1', //Bucket region - not required if same as AWS.config.region
apiVersion: '2006-03-01',
params: {Bucket: bucketName}
});

//Refresh and Upload
AWS.config.credentials.refresh(function(){
var IdentityId = s3.config.credentials.params.IdentityId;
var keyName = "cognito/"+IdentityId+"/it_works.txt";
var params = {Bucket: bucketName, Key: keyName, Body: 'Hello World!'};
s3.putObject(params, function (err, data) {
if (err)
console.log(err)
else
console.log("Successfully uploaded data to " + bucketName + "/" + keyName);
});
});
//Console: Successfully uploaded data to mybucket/cognito/us-east-1:c4db3eca-6ed0-af08-4aaa-a33aee2e994a/it_works.txt);
</script>

我的 IAM 权限策略是从这里借来的,如下所示:

{
"Version": "2012-10-17",
"Statement": [
{
"Action": ["s3:ListBucket"],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::mybucket"],
"Condition": {"StringLike": {"s3:prefix": ["${cognito-identity.amazonaws.com:sub}/*"]}}
},
{
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::mybucket/${cognito-identity.amazonaws.com:sub}/*"]
}
]
}

这一切都很好用,并以mybucket/cognito/us-east-1:c4db3eca-6ed0-af08-4aaa-a33aee2e994a/it_works.txt上传了一个文件

我想要的是设置一个以用户名命名的自定义子文件夹johnsmith.

我的问题是:

有没有办法将用户名作为变量传递以用作 IAM 角色权限,以便它能够上传到mybucket/cognito/johnsmith/而不是这个丑陋而漫长的mybucket/cognito/us-east-1:c4db3eca-6ed0-af08-4aaa-a33aee2e994a/

这些 IdentityId 太长了,很难处理。我想我还必须将 IdentityId 保存在我的数据库中?

令牌中的信息是"可解码的",还是只是一个安全的哈希值。我注意到,当我刷新时,只有它的后半部分会发生变化,而当我更改用户名时,整个令牌都会发生变化。

请让我知道如何使用 Cognito 设置自定义子文件夹,而不是 IdentityId${cognito-identity.amazonaws.com:sub}我发现这篇文章表明您可以使用${aws:username}/*但是如何将用户名传递到OpenID令牌或其他地方?

用户名没有 IAM 策略变量,但如果您想付出一些努力,我认为您可以做一些工作。

  1. 更新 Lambda。使用 Cognito SDK 执行 ListUsers。您可以提供子并取回用户名。将数据写入格式为mybucket/username/sub的文件夹
  2. 更新存储桶策略,在用户名所在的位置放置通配符。

例如:

Resource": ["arn:aws:s3:::mybucket/*/${cognito-identity.amazonaws.com:sub}/*"]

您仍将sub作为文件夹名称,但它位于用户名文件夹下,因此浏览文件夹将很容易。

不幸的是,这是不可能的。您看到的用户名变量仅适用于 IAM 用户名。IAM 策略无法从认知用户池读取任何内容。您看到的子变量与用户池中显示的子变量完全不同。子实际上来自没有任何用户名的身份池。也许AWS将来会允许这样做,但目前这是不可能的。

但是,您可以在创建应用程序时简单地向用户隐藏此信息。如果您通过控制台登录,则只会在存储桶路径中看到这个大的子变量。我构建了一个类似的应用程序,我只是向用户显示此变量中的所有内容,就好像它是他们的根文件夹一样。

相关内容

  • 没有找到相关文章

最新更新