gpt4 book ai didi

javascript - 从 Meteor 移动应用程序向 S3 进行身份验证

转载 作者:行者123 更新时间:2023-11-28 05:30:10 25 4
gpt4 key购买 nike

我有一个 Meteor Mobile 应用程序,可以访问我的 S3 存储桶中存储的大量照片。这些照片是用户上传的并且经常更改。我不希望不使用我的应用程序的任何人都可以访问这些照片。 (即:这些照片只能从我的应用程序中查看,直接在浏览器中访问网址不会加载它们)。

实现这一目标的最佳方法是什么? AWS Cognito 似乎是合乎逻辑的选择,但实现起来似乎并不容易,而且我不太确定客户端获得 Cognito 身份后如何向 AWS 进行身份验证。

我的另一个想法是在每个 URL 上放置一个只读 AWS key 并以这种方式进行身份验证,但这几乎毫无意义。找出 key 和 secret 真的很容易。

编辑:

具体来说,图像的 URL 位于 Mongo 集合中,我将它们传递到模板中。因此,S3 资源只是加载了图像标签 ( <img src=" )。像 AWS STS 这样的东西听起来是一个不错的选择,但是当我像这样加载它们时,我不知道如何在 header 中传递 token 。将它们作为预签名查询字符串来执行似乎效率很低。

另一个选项是使用 referrer 限制访问 header ,like this issue 。但正如 Martijn 所说,这并不是一种真正安全的方法。

最佳答案

经过一些研究和测试,我自己解决了这个问题。我的最终解决方案是使用 referer header 来限制对我的 S3 存储桶的访问。我创建了一个更安全、更详细的解决方案(见下文),但它带来了性能损失,不适用于我的应用程序。我的应用程序基于查看照片和视频,不可能立即加载它们。尽管如此,我觉得它对于大多数用例来说可能是一个足够的解决方案。由于我的应用不是高度敏感,因此 referer header 对我来说就足够了。 Here is how to use the http header referer to limit access to a bucket.

使用亚马逊 STS 的解决方案:

首先,您需要在 server 上都拥有 AWS 开发工具包。和 client.没有可用的 Meteor 的最新软件包,因此我创建了自己的软件包。 (我将很快发布它,并在发布后在此处放置一个链接。)

在服务器上,您必须使用能够承担 Angular 色的凭据。要担任的 Angular 色必须与担任该 Angular 色的用户具有信任关系。 Article on using IAM. -Article on using credentials with SDK

server.js 文件中,我创建了一个可以从客户端调用的 Meteor 方法。它首先检查用户是否登录。如果是,它会检查当前的临时凭证是否在接下来的 5 分钟内到期。如果是,我会发出新的凭据,并将它们写入用户文档或作为回调返回。如果它们在接下来的 5 分钟内没有过期,我将返回他们当前的临时凭证。

您必须使用 Meteor.bindEnvironment进行回调。 See docs

Meteor.methods({
'awsKey': function(){
if (Meteor.userId()){
var user = Meteor.userId();
var now = moment(new Date());
var userDoc = Meteor.users.findOne({_id: user});
var expire = moment(userDoc.aws.expiration);
var fiveMinutes = 5 * 60 * 1000;
var fut = new Future();

if(moment.duration(expire.diff(now))._milliseconds < fiveMinutes ){
var params = {
RoleArn: 'arn:aws:iam::556754141176:role/RoleToAssume',
RoleSessionName: 'SessionName',
DurationSeconds: 3600 //1 Hour
};
var sts = new AWS.STS();
sts.assumeRole(params, Meteor.bindEnvironment((err, data) => {
if (err){
fut.throw(new Error(err));
}else{
Meteor.users.update({_id: user}, {$set: {aws: {accessKey: data.Credentials.AccessKeyId, secretKey: data.Credentials.SecretAccessKey, sessionToken: data.Credentials.SessionToken, expiration: data.Credentials.Expiration}}});
fut.return(data.Credentials);
}
}));
return fut.wait();
}else{
return userDoc.aws;
}
}
}
}
});

然后您可以手动调用此方法,也可以在 Meteor.startup 上的 setInterval 中调用此方法。

  Meteor.setInterval(function(){
if(Meteor.userId()){
Meteor.call('awsKey', function(err, data){
if (err){
console.log(err);
}else{
if(data.accessKey){
Session.set('accessKey', data.accessKey);
Session.set('secretKey', data.secretKey);
Session.set('sessionToken', data.sessionToken);
}else{
Session.set('accessKey', data.AccessKeyId);
Session.set('secretKey', data.SecretAccessKey);
Session.set('sessionToken', data.SessionToken);
}
}
});
}
}, 300000); //5 Minute interval

这种方式只是从回调中设置 session 变量中的键。您也可以通过查询用户的文档来获取它们来完成此操作。

然后,您可以使用这些临时凭据来获取您尝试在存储桶中访问的对象的签名 URL。

我通过在模板中将对象名称传递给它来将其放入模板助手中:

{{getAwsUrl imageName}}

Template.templateName.helpers({

'getAwsUrl': function(filename){
var accessKey = Session.get('accessKey');
var secretKey = Session.get('secretKey');
var sessionToken = Session.get('sessionToken');
var filename = filename;
var params = {Bucket: 'bucketName', Key: filename, Expires: 6000};
new AWS.S3({accessKeyId: accessKey, secretAccessKey: secretKey, sessionToken: sessionToken, region: 'us-west-2'}).getSignedUrl('getObject', params, function (err, url) {
if (err) {
console.log("Error:" +err);
}else{
result = url;
}
});
return result;
}

});

这就是全部内容了!我确信这可以改进得更好,但这只是我在快速测试时想到的。就像我说的,它应该适用于大多数用例。我的那个没有。由于某种原因,当您尝试在这些签名 URL 的 img src 上切换 visibility:visible|hidden; 时,它们的加载时间将比仅设置 URL 花费的时间长得多直接地。这肯定是因为亚马逊必须在返回对象之前解密其签名的 URL。

感谢Mikkel为方向。

关于javascript - 从 Meteor 移动应用程序向 S3 进行身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39757309/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com