转载

Amazon Cognito:管理移动账户数据

在这个个人经常使用多种智能设备访问移动应用的世界中,Amazon Cognito允许对访问请求进行安全认证。

Amazon Cognito 是一项亚马逊web服务,跨设备提供移动身份管理和数据同步。我们首先花点时间来确保我们明白Cognito是做什么的,然后我们以一个简单的Java应用进一步深入。

首先,什么是数据同步和身份管理呢?

随着供个人使用多种智能设备进行访问的移动应用的激增,保持账户的一致性和更新已成为一项挑战。其窍门是有效地管理用户数据,像设置,偏好,和应用状态。现在启动一个简单应用需要基础设施管理诸如数据同步,网络状态,和存储位置这样的细节。

Amazon Cognito解决了这些难题,允许开发者更加专注于应用开发。

在Amazon Cognito面世之前,Identity Management(身份管理)在获取对AWS资源的应用访问权之前自然需要进行认证。应用往往需要通过一个有效的AWS账户ID和证书(Secret Key(秘密金钥)和Access Key(访问密钥))。动态保护AWS证书一直是一个关注点:开发者不能在应用程序内部对证书进行硬编码处理,因为那样违反了最优实践。在加密文件系统中存储证书听起来也不是一个完美的解决方案。

Amazon Cognito提供了一种可靠安全的AWS资源访问方式,无需预先生成证书(尽管仍需AWS账户详情)。系统赋予用户唯一的识别符,确保跨设备时,用户识别符仍然是一致的。

这是如何运作的呢?Amazon Cognito通过公共登录供应商(像Google和Facebook)使用户得到认证。现在有Cognito控制全局,你的应用就在准确访问所需AWS资源的同时,其权限也得到了严格的遵守。在你确认证书未暴露于危险之中的同时,你的用户也将享受他们的流畅体验。

下图展示了一个应用在试图通过公共登录供应商访问AWS业务时所经历的认证流程:

Amazon Cognito:管理移动账户数据

开发者认证系统

由于种种原因,移动应用用户有时选择不使用公共登录供应商的账户,而是更喜欢应用本身所提供的认证机制。Amazon Cognito足够灵活,允许应用开发人员使用他们自己的认证系统。

下图展示了一个应用在试图通过开发者认证系统访问AWS业务时所经历的认证流程:

Amazon Cognito:管理移动账户数据

Amazon Cognito入门

现在让我们来看看认证实际上是如何进行的。我们将试着写一些应用代码来熟悉如何调用API,像GetId,GetOpenIdToken,AssumeRoleWithWebIdentity,最重要的AWS Security Token Service (STS,安全令牌服务)。

在本示例中,我们将使用这样的一个Amazon Cognito,它包含一个应用,该应用不需AWS证书,但是仍能从本地文件系统访问AWS S3服务并上传文件:

1. 在Amazon Cognito控制台中创建一个身份池。该身份池看起来如下图所示。它使你能够为应用用户创建一个新的IAM角色(或使用既存的一个角色)。一旦你拥有了一个IAM角色,它将能使你使用临时证书访问所需的AWS资源。我们待会儿就会看到身份池详细信息是如何用于应用代码中的。

Amazon Cognito:管理移动账户数据

正如你可以看到的,通过选中 Enable access to unauthenticated identities ,我们正在允许未经授权的用户。但是正因为如此,我们不得不很谨慎地将该特权赋予该用户。我们可以通过为相应的角色附加一项合适的策略从而实现对赋予特权的控制。

对我们的示例而言,对 Cognito_testcognitoidentityUnauth_Role should的策略应该如下所示:

Amazon Cognito:管理移动账户数据

2. 记下ARN,因为我们在写应用时会用到它。点击Show ARN获得ARN的详情,如下图所示:

Amazon Cognito:管理移动账户数据

3.  现在,如果你正在运行Eclipse,创建一个简单的Java项目,该项目包含一个名为 TestAWSCognitoIdentityProvider 的类,为该类使用下面的内容:

Javaimport java.io.File; import java.util.Date; import com.amazonaws.auth.AWSSessionCredentials; import com.amazonaws.auth.AnonymousAWSCredentials; import com.amazonaws.auth.BasicSessionCredentials; import com.amazonaws.services.cognitoidentity.AmazonCognitoIdentity; import com.amazonaws.services.cognitoidentity.AmazonCognitoIdentityClient; import com.amazonaws.services.securitytoken.model.Credentials; import com.amazonaws.services.cognitoidentity.model.GetIdRequest; import com.amazonaws.services.cognitoidentity.model.GetIdResult; import com.amazonaws.services.cognitoidentity.model.GetOpenIdTokenRequest; import com.amazonaws.services.cognitoidentity.model.GetOpenIdTokenResult; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.model.PutObjectRequest; import com.amazonaws.services.securitytoken.AWSSecurityTokenService; import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient; import com.amazonaws.services.securitytoken.model.AssumeRoleWithWebIdentityRequest; import com.amazonaws.services.securitytoken.model.AssumeRoleWithWebIdentityResult; public class TestAWSCognitoIdentityProvider {   /**   As far a   * @param args   */   public static void main(String[] args) {  // initialize the Cognito identity client with a set  // of anonymous AWS credentials  AmazonCognitoIdentity identityClient = new AmazonCognitoIdentityClient(new AnonymousAWSCredentials());  identityClient.setEndpoint(“<<set endpoint for AWS cognito>>”);  GetIdRequest idRequest = new GetIdRequest();  idRequest.setAccountId(“<<Here you should give your aws accound number>>“);  idRequest.setIdentityPoolId(“<<Provide endpoint for identitypool>>“);  GetIdResult idResp = identityClient.getId(idRequest);  String identityId = idResp.getIdentityId();  GetOpenIdTokenRequest tokenRequest = new GetOpenIdTokenRequest();  tokenRequest.setIdentityId(identityId);  GetOpenIdTokenResult tokenResp = identityClient.getOpenIdToken(tokenRequest);  String openIdToken = tokenResp.getToken();  AWSSecurityTokenService stsClient = new AWSSecurityTokenServiceClient(new AnonymousAWSCredentials());  AssumeRoleWithWebIdentityRequest stsReq = new AssumeRoleWithWebIdentityRequest();  stsReq.setRoleArn(“<<Provde the ARN that was noted down in step 2>>“);  stsReq.setWebIdentityToken(openIdToken);  stsReq.setRoleSessionName(“AppTestSession”);  AssumeRoleWithWebIdentityResult stsResp = stsClient.assumeRoleWithWebIdentity(stsReq);  Credentials stsCredentials = stsResp.getCredentials();  AWSSessionCredentials sessionCredentials = new BasicSessionCredentials(    stsCredentials.getAccessKeyId(),    stsCredentials.getSecretAccessKey(),    stsCredentials.getSessionToken()  );  Date sessionCredentialsExpiration = stsCredentials.getExpiration();  System.out.println(sessionCredentials.getAWSAccessKeyId());  String bucketName = “<<Existing bucket name>>”;  String keyName = “cognitokey”;  String uploadFileName = “<<File name with path>>”;  AmazonS3 s3client = new AmazonS3Client(sessionCredentials);  s3client.setEndpoint(“<<Provide S3 endpoint>>”);  File file = new File(uploadFileName);  s3client.putObject(new PutObjectRequest(bucketName, keyName, file));   } }  import java.io.File;import java.util.Date;import com.amazonaws.auth.AWSSessionCredentials;import com.amazonaws.auth.AnonymousAWSCredentials;import com.amazonaws.auth.BasicSessionCredentials;import com.amazonaws.services.cognitoidentity.AmazonCognitoIdentity;import com.amazonaws.services.cognitoidentity.AmazonCognitoIdentityClient;import com.amazonaws.services.securitytoken.model.Credentials;import com.amazonaws.services.cognitoidentity.model.GetIdRequest;import com.amazonaws.services.cognitoidentity.model.GetIdResult;import com.amazonaws.services.cognitoidentity.model.GetOpenIdTokenRequest;import com.amazonaws.services.cognitoidentity.model.GetOpenIdTokenResult;import com.amazonaws.services.s3.AmazonS3;import com.amazonaws.services.s3.AmazonS3Client;import com.amazonaws.services.s3.model.PutObjectRequest;import com.amazonaws.services.securitytoken.AWSSecurityTokenService;import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient;import com.amazonaws.services.securitytoken.model.AssumeRoleWithWebIdentityRequest;import com.amazonaws.services.securitytoken.model.AssumeRoleWithWebIdentityResult; public class TestAWSCognitoIdentityProvider {   /**  As far a  * @param args  */   public static void main(String[] args) {  // initialize the Cognito identity client with a set // of anonymous AWS credentials AmazonCognitoIdentity identityClient = new AmazonCognitoIdentityClient(new AnonymousAWSCredentials()); identityClient.setEndpoint(“<<set endpoint for AWS cognito>>”);  GetIdRequest idRequest = new GetIdRequest(); idRequest.setAccountId(“<<Here you should give your aws accound number>>“); idRequest.setIdentityPoolId(“<<Provide endpoint for identitypool>>“); GetIdResult idResp = identityClient.getId(idRequest);  String identityId = idResp.getIdentityId(); GetOpenIdTokenRequest tokenRequest = new GetOpenIdTokenRequest(); tokenRequest.setIdentityId(identityId); GetOpenIdTokenResult tokenResp = identityClient.getOpenIdToken(tokenRequest); String openIdToken = tokenResp.getToken();  AWSSecurityTokenService stsClient = new AWSSecurityTokenServiceClient(new AnonymousAWSCredentials());  AssumeRoleWithWebIdentityRequest stsReq = new AssumeRoleWithWebIdentityRequest(); stsReq.setRoleArn(“<<Provde the ARN that was noted down in step 2>>“); stsReq.setWebIdentityToken(openIdToken); stsReq.setRoleSessionName(“AppTestSession”);  AssumeRoleWithWebIdentityResult stsResp = stsClient.assumeRoleWithWebIdentity(stsReq); Credentials stsCredentials = stsResp.getCredentials();  AWSSessionCredentials sessionCredentials = new BasicSessionCredentials(   stsCredentials.getAccessKeyId(),   stsCredentials.getSecretAccessKey(),   stsCredentials.getSessionToken() ); Date sessionCredentialsExpiration = stsCredentials.getExpiration();  System.out.println(sessionCredentials.getAWSAccessKeyId());  String bucketName = “<<Existing bucket name>>”; String keyName = “cognitokey”; String uploadFileName = “<<File name with path>>”; AmazonS3 s3client = new AmazonS3Client(sessionCredentials); s3client.setEndpoint(“<<Provide S3 endpoint>>”);  File file = new File(uploadFileName); s3client.putObject(new PutObjectRequest(bucketName, keyName, file));  }} 

现在让我们努力地理解这些代码。一旦你创建了身份池,你就需要调用API GetId ,提供你的AWS账户和身份池细节以便为你的终端用户检索一个唯一的识别符(也称为Cognito ID)。

Amazon Cognito:管理移动账户数据

现在,使用Cognito ID获取一个OpenID令牌。和STS交换你的OpenID令牌,你就能获取临时的,拥有有限特权的AWS证书。

Amazon Cognito:管理移动账户数据

AssumeRolewithWebIdentity 为用户返回了一组临时的安全证书。这些用户已在移动或web应用中通过一个与OpenID Connect兼容的web身份供应商获得了认证。除了 AssumeRolewithWebIdentity ,STS也 支持其他的动作 。这就解释了我们如何使用带有临时证书的AWS S3客户端上传文件,而不需呈现用户的永久秘密金钥和访问密钥。

注意:为了避免编译/运行错误,确保你已在构建路径中使这些文件可用。或者如果你正在使用Maven,确保你已照顾到所有的依赖关系。

Amazon Cognito:管理移动账户数据

4. 一旦一切准备就绪,你就可以运行这个Java程序,然后在S3中验证文件是否已被上传。

概要:关于Amazon Cognito

  • Amazon Cognito可与Amazon,Facebook,Twitter,Digits,Google,和其他任何与OpenID Connect兼容的身份供应商一起使用。
  • Amazon Cognito支持未经授权的客座用户(比如,那些未经你自己的身份系统或支持的身份供应商认证的用户)。
  • Cognito事件可与Amazon Lambda集成。
  • 数据在Amazon Cognito同步存储中被静态加密,所有的身份数据通过HTTPS传输。
  • Amazon Cognito按照存储在Amazon Cognito同步存储中的应用数据量和实施的同步操作的次数进行计费。有了AWS Free Tier(AWS免费使用层),你在长达12个月的时间内,每月可免费使用10GB的同步存储空间,进行一百万次同步操作。在12个月期满后,每个月每GB的同步存储空间花费0.15美元,每一万次同步操作花费0.15美元。
  • 目前AWS Cognito在美国东部(北弗吉尼亚),欧洲(爱尔兰),和亚太(东京)地区可用。
  • AWS Cognito流允许用户身份数据从 AWS Cognito 流向 Amazon Kinesis
正文到此结束
Loading...