AWS S3 - 如何为 Android 获取正确的凭证?

Posted

技术标签:

【中文标题】AWS S3 - 如何为 Android 获取正确的凭证?【英文标题】:AWS S3 - How to get credentials correct for Android? 【发布时间】:2017-03-23 21:15:50 【问题描述】:

我正在使用 S3 制作一个 android 应用程序,以便用户可以将内容上传到 S3 服务器。对于 AWS 令牌,我们使用自己的服务器来获取以下内容。

AwsToken.java 是以下 json 的 POJO。


  "id": "us-east-1:xxxxx",
  "token": "xxxxx",
  "region": "us-east-1",
  "identityPoolId": "us-east-1:xxxxx",
  "loginProvider": "xxxxx"
   

然后我尝试使用它来创建 identityProvider 和 credentialsProvider 来获取 AmazonS3Client 和 TransferUtility。

KOIAWSAuthenticatedIdentityProvider identityProvider = new KOIAWSAuthenticatedIdentityProvider(awsToken);

CognitoCachingCredentialsProvider cognitoCachingCredentialsProvider = new CognitoCachingCredentialsProvider(
    getApplicationContext(), // Context
    identityProvider,
    Regions.US_EAST_1 // Region
);

AmazonS3Client sS3Client = new AmazonS3Client(cognitoCachingCredentialsProvider);
TransferUtility transferUtility = new TransferUtility(sS3Client, getApplicationContext());

KOIAWSAuthenticatedIdentityProvider.java

package com.krossover.network.aws;

import com.amazonaws.auth.AWSCognitoIdentityProvider;
import com.amazonaws.auth.IdentityChangedListener;
import com.krossover.network.models.AWSToken;

import java.util.Map;

/**
 * Created by paulshin on 9/26/16.
 */
public class KOIAWSAuthenticatedIdentityProvider implements AWSCognitoIdentityProvider 
    private AWSToken awsToken;

    public KOIAWSAuthenticatedIdentityProvider(AWSToken awsToken) 
        this.awsToken = awsToken;
    

    @Override
    public String getIdentityId() 
        return awsToken.id;
    

    @Override
    public String getIdentityPoolId() 
        return awsToken.identityPoolId;
    

    @Override
    public void setLogins(Map<String, String> loginsMap) 

    

    @Override
    public Map<String, String> getLogins() 
        return null;
    

    @Override
    public boolean isAuthenticated() 
        return true;
    

    @Override
    public void registerIdentityChangedListener(IdentityChangedListener listener) 

    

    @Override
    public void unregisterIdentityChangedListener(IdentityChangedListener listener) 

    

    @Override
    public void identityChanged(String newIdentity) 

    

    @Override
    public void clearListeners() 

    

    @Override
    public String getToken() 
        return awsToken.token;
    

    @Override
    public String refresh() 
        return null;
    

问题是我不断收到这个错误

E/CognitoCachingCredentialsProvider: Failure to get credentials
    com.amazonaws.services.cognitoidentity.model.NotAuthorizedException: Access to Identity 'us-east-1:xxxxx' is forbidden. (Service: AmazonCognitoIdentity; Status Code: 400; Error Code: NotAuthorizedException; Request ID: xxxxx)
        at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:712)
        at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:388)
        at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:199)
        at com.amazonaws.services.cognitoidentity.AmazonCognitoIdentityClient.invoke(AmazonCognitoIdentityClient.java:558)
        at com.amazonaws.services.cognitoidentity.AmazonCognitoIdentityClient.getCredentialsForIdentity(AmazonCognitoIdentityClient.java:388)
        at com.amazonaws.auth.CognitoCredentialsProvider.populateCredentialsWithCognito(CognitoCredentialsProvider.java:651)
        at com.amazonaws.auth.CognitoCredentialsProvider.startSession(CognitoCredentialsProvider.java:577)
        at com.amazonaws.auth.CognitoCredentialsProvider.getCredentials(CognitoCredentialsProvider.java:371)
        at com.amazonaws.auth.CognitoCachingCredentialsProvider.getCredentials(CognitoCachingCredentialsProvider.java:441)
        at com.amazonaws.auth.CognitoCachingCredentialsProvider.getCredentials(CognitoCachingCredentialsProvider.java:76)
        at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4369)
        at com.amazonaws.services.s3.AmazonS3Client.initiateMultipartUpload(AmazonS3Client.java:3287)
        at com.amazonaws.mobileconnectors.s3.transferutility.UploadTask.initiateMultipartUpload(UploadTask.java:252)
        at com.amazonaws.mobileconnectors.s3.transferutility.UploadTask.uploadMultipartAndWaitForCompletion(UploadTask.java:100)
        at com.amazonaws.mobileconnectors.s3.transferutility.UploadTask.call(UploadTask.java:80)
        at com.amazonaws.mobileconnectors.s3.transferutility.UploadTask.call(UploadTask.java:44)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
    at java.lang.Thread.run(Thread.java:818)
 E/UploadTask: Error initiating multipart upload: 31 due to Access to Identity 'us-east-1:xxxxx' is forbidden. (Service: AmazonCognitoIdentity; Status Code: 400; Error Code: NotAuthorizedException; Request ID: xxxxx)

我们的 ios 应用程序具有非常相似的逻辑,并且运行良好,并且从未出现访问禁止错误。我不知道为什么我从 Android 库中获取它。

仅供参考,这是 KOIAWSAuthenticatedIdentityProvider.java 的 iOS 对应项

class KOIAWSAuthenticatedIdentityProvider: AWSCognitoCredentialsProviderHelper 

    private var awsToken: String

    init(regionType: AWSRegionType,
         identityPoolId: String,
         providerName: String,
         identityId: String,
         token: String)
    
        self.awsToken = token

        super.init(
            regionType: regionType,
            identityPoolId: identityPoolId,
            useEnhancedFlow: true,
            identityProviderManager: nil)

        self.identityId = identityId
    

    override func token() -> AWSTask 
        return AWSTask(result: self.awsToken)
    

我看到不同之处在于 Android 与 useEnhancedFlow: true" 没有任何关系..

有人知道吗?谢谢..

【问题讨论】:

【参考方案1】:

当它是一个经过身份验证的身份(已经有一个登录链接到它的身份)时,几乎总是会抛出对身份 x 的访问,但正在为该身份发出请求,但不包括登录名。 Cognito 要求您在尝试访问时提供 >= 1 个与经过身份验证的身份相关联的登录名。

您很可能遇到了这个问题,因为您子类化的类不是正确的。根据Cognito docs,您应该继承 AWSAbstractCognitoDeveloperIdentityProvider。

【讨论】:

以上是关于AWS S3 - 如何为 Android 获取正确的凭证?的主要内容,如果未能解决你的问题,请参考以下文章

如何为 Fargate 任务提供上传到 S3 的正确权限

如何为“无服务器”部署创建一个 s3 存储桶?

如何为AWS Lambda创建和压缩docker容器

如何为 AWS EC2 上托管的 Parse 服务器获取 APP_ID 和 CLIENT_KEY

如何为 tomcat beanstalk 设置正确的 SES 身份策略?

如何为多个 IAM 用户设置 S3 策略,以便每个人只能访问他们的个人存储桶文件夹?