在 React 中使用 aws-amplify 将文件上传到具有联合身份的 S3 时出错



当具有 Facebook 联合身份的用户尝试上传图像时,我收到错误:AWSS3Provider - 上传错误:"请求失败,状态代码为 403" 状态代码:403 禁止

注意到请求中的 URL,当用户使用联合身份 (Facebook) 进行身份验证时,看起来:
请求网址:https://my-gallery-api-dev-photorepos3bucket-XXXX.s3.us-east-2.amazonaws.com/private/undefined/1587639369473-image.jpg?x-id=PutObject

将放置上传图像的文件夹是"未定义">,而不是像从 AWS UserPool 进行身份验证的用户那样是有效的用户身份,请参阅:
请求网址:https://my-gallery-api-dev-photorepos3bucket-XXXX.s3.us-east-2.amazonaws.com/private/us-east-2%3Aa2991437-264a-4652-a239-XXXXXXXXXXXX/1587636945392-image.jpg?x-id=PutObject

对于身份验证和上传,我使用的是 React aws 依赖项"aws-amplify": "^3.0.8"

脸书认证(脸书按钮):

async handleResponse(data) {
console.log("FB Response data:", data);
const { userID, accessToken: token, expiresIn } = data;
const expires_at = expiresIn * 1000 + new Date().getTime();
const user = { userID };
this.setState({ isLoading: true });
console.log("User:", user);
try {
const response = await Auth.federatedSignIn(
"facebook",
{ token, expires_at },
user
);
this.setState({ isLoading: false });
console.log("federatedSignIn Response:", response);
this.props.onLogin(response);
} catch (e) {
this.setState({ isLoading: false })
console.log("federatedSignIn Exception:", e);
alert(e.message);
this.handleError(e);
}
}

上传:

import { Storage } from "aws-amplify";
export async function s3Upload(file) {
const filename = `${Date.now()}-${file.name}`;
const stored = await Storage.vault.put(filename, file, {
contentType: file.type
});
return stored.key;
}
const attachment = this.file
? await s3Upload(this.file)
: null;

我知道 S3 拒绝了 403,因为 IAM 角色,我对经过身份验证的用户有:

# IAM role used for authenticated users
CognitoAuthRole:
Type: AWS::IAM::Role
Properties:
Path: /
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: 'Allow'
Principal:
Federated: 'cognito-identity.amazonaws.com'
Action:
- 'sts:AssumeRoleWithWebIdentity'
Condition:
StringEquals:
'cognito-identity.amazonaws.com:aud':
Ref: CognitoIdentityPool
'ForAnyValue:StringLike':
'cognito-identity.amazonaws.com:amr': authenticated
Policies:
- PolicyName: 'CognitoAuthorizedPolicy'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: 'Allow'
Action:
- 'mobileanalytics:PutEvents'
- 'cognito-sync:*'
- 'cognito-identity:*'
Resource: '*'
# Allow users to invoke our API
- Effect: 'Allow'
Action:
- 'execute-api:Invoke'
Resource:
Fn::Join:
- ''
-
- 'arn:aws:execute-api:'
- Ref: AWS::Region
- ':'
- Ref: AWS::AccountId
- ':'
- Ref: ApiGatewayRestApi
- '/*'
# Allow users to upload attachments to their
# folder inside our S3 bucket
- Effect: 'Allow'
Action:
- 's3:*'
Resource:
- Fn::Join:
- ''
-
- Fn::GetAtt: [PhotoRepoS3Bucket, Arn]
- '/private/**${cognito-identity.amazonaws.com:sub}/***'
- Fn::Join:
- ''
-
- Fn::GetAtt: [PhotoRepoS3Bucket, Arn]
- '/private/**${cognito-identity.amazonaws.com:sub}**'

它适用于在 AWS 用户池(电子邮件、密码)中注册的用户,但对于联合身份用户,AWS 用户池中没有仅在联合身份中的记录,因此不会为这些用户找到cognito-identity.amazonaws.com:sub,并且目录"未定义">不属于使用联合身份标识的用户的角色允许。

请告知:
1. 在哪里/如何修复 URL 中的"未定义">
阿拉伯数字。另外,我可能希望将上传URL中的thouse ID替换为我将在不久的将来添加的用户数据库中的通用用户ID。如何修复 IAM 角色以使用自定义 ID?

我在做无服务器堆栈教程时遇到了同样的问题

当您使用 AWS Amplify 执行额外信用> React> Facebook Unlock with Cognito 时,会出现此错误,因为您注意到如果您通过 Facebook 身份验证,上传文件将失败。

将 PUT 发送到以下位置时会出现错误:

https://<bucket>.s3.amazonaws.com/private/<identity-id>/<file>......<identity-id>未定义,因此 PUT 失败。

如果您记录运行登录命令时获得的内容,则可以跟踪此取消定义的来源。例如,当您使用电子邮件和密码登录时,如果您这样做:

await Auth.signIn(fields.email, fields.password);
const currCreds = await Auth.currentCredentials();
console.log('currCreds', currCreds);

。您可以看到identityId设置正确。

另一方面,当您通过Auth.federatedSignIn登录Facebook时,如果您记录了响应,则不会identityId。注意:如果您之前使用电子邮件和密码登录,它将保持不变,因此这种错误配置也会导致上传失败。

我使用的解决方法是添加一个简单的lambda,它返回登录用户的identityId,因此一旦用户使用Facebook登录,我们就会要求它,然后可以使用AWS.S3().putObject将PUT发送到正确的URL

。如果您想尝试一下,请考虑您应该在https中托管您的React应用程序,因为Facebook不允许http域。您可以设置此添加HTTPS=true到您的 React .env 文件中。

您可以检查我的存储库作为示例:
接口
前端

相关内容

  • 没有找到相关文章

最新更新