You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular项目:Cognito用户关联个人S3桶权限及凭证缺失问题

问题描述

开发的系统包含两部分:桌面应用支持用户登录后上传文件到个人Amazon S3桶;网页端允许用户通过Cognito账号登录,查看/下载自己桶内的文件。目前桌面应用功能正常,但网页端无法关联Cognito用户与对应S3桶的权限,调用ListBuckets接口时返回Error: Credential is missing错误。

AWS Amplify认证代码(输入凭证可成功获取用户)

export class CognitoService {

  private authenticationSubject: BehaviorSubject<any>;

  constructor() {
    Amplify.configure({
      Auth: environment.cognito,
    });

    this.authenticationSubject = new BehaviorSubject<boolean>(false);
  }


  public signIn(user: IUser): Promise<any> {
    return Auth.signIn(user.username, user.password)
      .then(returnedUser => {
        if (returnedUser.challengeName === 'NEW_PASSWORD_REQUIRED') {
          Auth.completeNewPassword(returnedUser, user.password)
            .then(user => {
              return user
            });
        }
      })
  }
  public getUser(): Promise<any> {
    return Auth.currentUserInfo();
  }
}

获取数据代码(获取S3桶请求失败)

export class DataComponent implements OnInit{
  user: IUser;

 constructor(private cognitoService: CognitoService, private s3Service: S3Service) {
    this.user = {} as IUser;
  }
  public ngOnInit(): void {
    this.cognitoService.getUser()
    .then((user: any) => {
      this.user = user.attributes;
    });
  }
  public getBuckets(): void {
    this.s3Service.getBuckets()
    .then((response: any) => {
      console.log(response)
    })
  }
}

获取桶的S3服务代码(怀疑需修改此处)

export class S3Service {
    constructor() {
        Amplify.configure({
            Auth: environment.cognito,
        });
    }

    public async getBuckets() {
        const client = new S3Client({region: 'us-west-2'});
        const input = {};
        const command = new ListBucketsCommand(input);
        const response = await client.send(command);
    }
}

环境配置

export const environment = {
    cognito: {
        userPoolId: 'xxx',
        userPoolWebClientId: 'xxx',
    },
}

解决方案

问题核心是S3客户端未获取到Cognito用户的临时凭证,同时代码存在几处需修正的细节:

1. 修正S3Service,注入Cognito凭证

先安装依赖:@aws-sdk/credential-provider-cognito-identity,然后修改S3Service代码:

import { Auth } from 'aws-amplify';
import { S3Client, ListBucketsCommand } from '@aws-sdk/client-s3';
import { fromCognitoIdentityPool } from '@aws-sdk/credential-provider-cognito-identity';

export class S3Service {
    // 无需重复配置Amplify,CognitoService已完成初始化
    constructor() {}

    public async getBuckets() {
        // 校验用户登录状态
        const authenticatedUser = await Auth.currentAuthenticatedUser();
        if (!authenticatedUser) throw new Error('用户未登录');

        // 获取Cognito身份凭证
        await Auth.currentUserCredentials();
        
        // 配置S3客户端,关联Cognito身份池临时凭证
        const client = new S3Client({
            region: 'us-west-2',
            credentials: fromCognitoIdentityPool({
                clientConfig: { region: 'us-west-2' },
                identityPoolId: environment.cognito.identityPoolId, // 需在环境变量中添加身份池ID
                logins: {
                    [`cognito-idp.us-west-2.amazonaws.com/${environment.cognito.userPoolId}`]: 
                        authenticatedUser.signInUserSession.idToken.jwtToken
                }
            })
        });

        const command = new ListBucketsCommand({});
        const response = await client.send(command);
        return response;
    }
}

2. 更新环境配置,添加Cognito身份池ID

身份池是关联用户池与S3权限的核心,补充环境变量:

export const environment = {
    cognito: {
        userPoolId: 'xxx',
        userPoolWebClientId: 'xxx',
        identityPoolId: 'us-west-2:xxxx-xxxx-xxxx-xxxx-xxxx' // 替换为你的身份池ID
    },
}

3. 修复CognitoService的signIn方法

原代码中completeNewPassword的Promise未返回,导致密码重置后无法正确获取用户信息:

public signIn(user: IUser): Promise<any> {
    return Auth.signIn(user.username, user.password)
        .then(returnedUser => {
            if (returnedUser.challengeName === 'NEW_PASSWORD_REQUIRED') {
                // 返回Promise确保外层等待操作完成
                return Auth.completeNewPassword(returnedUser, user.password);
            }
            return returnedUser;
        });
}

4. 配置Cognito身份池的S3权限

登录AWS控制台,进入Cognito身份池的认证角色,添加IAM策略(可根据需求缩小权限范围,比如仅允许访问用户专属桶):

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

5. 确保调用getBuckets时用户已登录

在DataComponent中,确认用户登录后再执行桶查询:

public ngOnInit(): void {
    this.cognitoService.getUser()
    .then((user: any) => {
        this.user = user.attributes;
        // 用户登录状态确认后再获取桶信息
        this.getBuckets();
    })
    .catch(err => {
        console.log('用户未登录', err);
    });
}

内容的提问来源于stack exchange,提问作者Cameron Greenwalt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 20:17:01