

适用于 JavaScript 的 AWS SDK v2 已终止支持。建议您迁移到 [适用于 JavaScript 的 AWS SDK v3](https://docs.aws.amazon.com//sdk-for-javascript/v3/developer-guide/)。有关更多详情和如何迁移的信息，请参阅本[公告](https://aws.amazon.com/blogs//developer/announcing-end-of-support-for-aws-sdk-for-javascript-v2/)。

# 在 Web 浏览器中设置凭证
<a name="setting-credentials-browser"></a>

有几种方法可以从浏览器脚本为 SDK 提供凭证。其中一些方法更安全，而另一些方法则在开发脚本时可以提供更大的便利。下面是按推荐顺序提供凭证的方法：

1. 使用 Amazon Cognito Identity 验证用户身份和提供凭证

1. 使用 Web 联合身份验证

1. 在脚本中硬编码

**警告**  
我们不建议在脚本中对您的 AWS 凭证进行硬编码。硬编码凭证存在暴露您的访问密钥 ID 和秘密访问密钥的风险。

**Topics**
+ [使用 Amazon Cognito Identity 验证用户身份](loading-browser-credentials-cognito.md)
+ [使用 Web 联合身份验证来验证用户身份](loading-browser-credentials-federated-id.md)
+ [Web 联合身份验证示例](config-web-identity-examples.md)

# 使用 Amazon Cognito Identity 验证用户身份
<a name="loading-browser-credentials-cognito"></a>

获取浏览器脚本 AWS 凭证的推荐方法是使用 Amazon Cognito Identity 凭证对象 `AWS.CognitoIdentityCredentials`。Amazon Cognito 支持通过第三方身份提供商对用户进行身份验证。

要使用 Amazon Cognito Identity，您必须先在 Amazon Cognito 控制台中创建一个身份池。身份池表示应用程序为用户提供的身份组。为用户提供的身份唯一地标识每个用户账户。Amazon Cognito 身份并不是凭证。可以在 AWS Security Token Service (AWS STS) 中使用 Web 联合身份验证支持为凭证交换这些身份。

Amazon Cognito 使用 `AWS.CognitoIdentityCredentials` 对象帮助您管理跨多个身份提供商的身份抽象。然后，在 AWS STS 中为凭证交换加载的身份。

## 配置 Amazon Cognito Identity 凭证对象
<a name="browser-cognito-configuration"></a>

如果您尚未创建身份池，则在配置 `AWS.CognitoIdentityCredentials` 之前，请先创建一个，以与 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito)中的浏览器脚本一起使用。为身份池创建并关联经过身份验证和未经身份验证的 IAM 角色。

未经身份验证的用户的身份未经过验证，因此，该角色很适合您的应用程序的来宾用户或用户身份验证与否无关紧要的情形。经过身份验证的用户可以通过证实其身份的第三方身份提供商登录到您的应用程序。确保您的资源的权限范围适当，让未经身份验证的用户无权访问这些资源。

通过关联的身份提供商配置身份池后，您可以使用 `AWS.CognitoIdentityCredentials` 验证用户身份。要将应用程序凭证配置为使用 `AWS.CognitoIdentityCredentials`，则为 `credentials` 或基于每个服务配置设置 `AWS.Config` 属性。以下示例使用 `AWS.Config`：

```
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
  IdentityPoolId: 'us-east-1:1699ebc0-7900-4099-b910-2df94f52a030',
  Logins: { // optional tokens, used for authenticated login
    'graph.facebook.com': 'FBTOKEN',
    'www.amazon.com': 'AMAZONTOKEN',
    'accounts.google.com': 'GOOGLETOKEN'
  }
});
```

可选的 `Logins` 属性是身份提供商名称到这些提供商身份令牌的映射。您如何从身份提供商获得令牌的方式取决于您使用的提供商。例如，如果 Facebook 是您的身份提供商之一，则您可以使用来自 [Facebook 软件开发工具包](https://developers.facebook.com/docs/facebook-login/web)的 `FB.login` 函数获取身份提供商令牌：

```
FB.login(function (response) {
  if (response.authResponse) { // logged in
    AWS.config.credentials = new AWS.CognitoIdentityCredentials({
      IdentityPoolId: 'us-east-1:1699ebc0-7900-4099-b910-2df94f52a030',
      Logins: {
        'graph.facebook.com': response.authResponse.accessToken
      }
    });

    s3 = new AWS.S3; // we can now create our service object

    console.log('You are now logged in.');
  } else {
    console.log('There was a problem logging you in.');
  }
});
```

## 将未经身份验证的用户切换为经过身份验证的用户
<a name="browser-switching-unauthenticated-users"></a>

Amazon Cognito 同时支持经过身份验证的用户和未经身份验证的用户。即使未经身份验证的用户不通过任何身份提供商登录，这些用户也有权访问您的资源。此级别的访问可用于向尚未登录的用户显示内容。即使每个未经身份验证的用户尚未单独登录和经过身份验证，这些用户在 Amazon Cognito 中也都具有唯一的身份。

### 最初未经身份验证的用户
<a name="browser-switching-initially-unauthenticated-user"></a>

用户通常从未经身份验证的角色开始，为此需要设置配置对象的凭证属性而不是 `Logins` 属性。在这种情况下，您的默认配置可能如下所示：

```
// set the default config object
var creds = new AWS.CognitoIdentityCredentials({
 IdentityPoolId: 'us-east-1:1699ebc0-7900-4099-b910-2df94f52a030'
});
AWS.config.credentials = creds;
```

### 切换为经过身份验证的用户
<a name="switch-to-authenticated"></a>

当未经身份验证的用户登录身份提供商并且您拥有令牌时，您可以通过调用可更新凭证对象和添加 `Logins` 令牌的自定义函数，来将用户从未经身份验证的用户切换为经过身份验证的用户：

```
// Called when an identity provider has a token for a logged in user
function userLoggedIn(providerName, token) {
  creds.params.Logins = creds.params.Logins || {};
  creds.params.Logins[providerName] = token;
                    
  // Expire credentials to refresh them on the next request
  creds.expired = true;
}
```

您还可以创建 `CognitoIdentityCredentials` 对象。如果这样做，则必须重置您创建的现有服务对象的凭证属性。仅在对象初始化时从全局配置读取服务对象。

有关 `CognitoIdentityCredentials` 对象的更多信息，请参阅 适用于 JavaScript 的 AWS SDK API 参考中的 [https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityCredentials.html](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityCredentials.html)。

# 使用 Web 联合身份验证来验证用户身份
<a name="loading-browser-credentials-federated-id"></a>

您可以使用 Web 身份联合验证直接配置各个身份提供商以访问 AWS 资源。AWS 目前支持通过多个身份提供商使用 Web 身份联合验证来验证用户身份：
+ [Login with Amazon](https://login.amazon.com)
+ [Facebook 登录](https://www.facebook.com/about/login)
+ [Google 登录](https://developers.google.com/identity/)

您必须首先向您的应用程序支持的提供商注册您的应用程序。接下来，创建 IAM 角色并为其设置权限。然后，您创建的 IAM 角色将通过相应的身份提供商授予您为其配置的权限。例如，您可以设置一个角色，允许通过 Facebook 登录的用户对您控制的特定 Amazon S3 桶具有读取权限。

有了配置了权限的 IAM 角色以及向所选身份提供商注册的应用程序之后，您可以将 SDK 设置为使用帮助程序代码获取 IAM 角色的凭证，如下所示：

```
AWS.config.credentials = new AWS.WebIdentityCredentials({
   RoleArn: 'arn:aws:iam::<AWS_ACCOUNT_ID>/:role/<WEB_IDENTITY_ROLE_NAME>',
   ProviderId: 'graph.facebook.com|www.amazon.com', // this is null for Google
   WebIdentityToken: ACCESS_TOKEN
});
```

`ProviderId` 参数中的值取决于指定的身份提供商。`WebIdentityToken` 参数中的值是从使用身份提供商成功登录时检索的访问令牌。有关如何为每个身份提供商配置和检索访问令牌的更多信息，请参阅身份提供商的相关文档。

## 步骤 1：向身份提供商注册
<a name="config-web-identity-register"></a>

首先，向您选择支持的身份提供商注册应用程序。系统会要求您提供信息来标识您的应用程序以及作者（在可能的情况下）。这可以确保身份提供商知道谁正在接收他们的用户信息。在每种情况下，身份提供商将发出用于配置用户角色的应用程序 ID。

## 步骤 2：为身份提供商创建 IAM 角色
<a name="config-web-identity-role"></a>

从身份提供商获取应用程序 ID 后，转到 IAM 控制台（地址：[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)）以创建新的 IAM 角色。

**为身份提供商创建 IAM 角色**

1. 转到控制台的**角色**部分，然后选择**创建新角色**。

1. 键入新角色的名称，以帮助您跟踪其使用情况，例如 **facebookIdentity**，然后选择**下一步**。

1. 在**选择角色类型**中，选择**用于身份提供商访问的角色**。

1. 对于**授予 Web 身份提供商访问权限**，选择**选择**。

1. 在**身份提供商**列表中，选择要为此 IAM 角色使用的身份提供商。  
![\[选择“用于身份提供商访问的角色”。\]](http://docs.aws.amazon.com/zh_cn/sdk-for-javascript/v2/developer-guide/images/iam-provider-select.png)

1. 在**应用程序 ID** 中键入身份提供商提供的应用程序 ID，然后选择**下一步**。

1. 配置要公开的资源的权限，以允许访问特定资源上的特定操作。有关 IAM 权限的更多信息，请参阅《IAM 用户指南》**中的 [AWS IAM 权限概述](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_permissions.html)。查看并根据需要自定义角色的信任关系，然后选择**下一步**。

1. 附加您需要的其他政策，然后选择**下一步**。有关 IAM policy 的更多信息，请参阅《IAM 用户指南》**中的 [IAM policy 概述](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html)。

1. 检查新角色，然后选择**创建角色**。

您可以为角色提供其他约束，例如将其限定为特定用户 ID。如果角色授予对资源的写入权限，请确保正确地将角色限定为具有正确权限的用户，否则具有 Amazon、Facebook 或 Google 身份的任何用户都将能够修改应用程序中的资源。

有关在 IAM 中使用 Web 身份联合验证的更多信息，请参阅《IAM 用户指南》**中的[关于 Web 身份联合验证](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html)。

## 步骤 3：登录后获取提供商访问令牌
<a name="config-web-identity-obtain-token"></a>

使用身份提供商的开发工具包为您的应用程序设置登录操作。您可以使用 OAuth 或 OpenID 从身份提供商下载并安装允许用户登录的 JavaScript 开发工具包。有关如何在应用程序中下载和设置开发工具包代码的信息，请参阅身份提供商的开发工具包文档：
+ [Login with Amazon](https://login.amazon.com/website)
+ [Facebook 登录](https://developers.facebook.com/docs/javascript)
+ [Google 登录](https://developers.google.com/identity/)

## 步骤 4：获取临时凭证
<a name="config-web-identity-get-credentials"></a>

在配置应用程序、角色和资源权限后，将代码添加到应用程序以获取临时凭证。通过 AWS Security Token Service 使用 Web 联合身份验证提供这些凭证。用户登录到身份提供商，该提供商返回访问令牌。针对您为此身份提供者创建的 IAM 角色，使用 ARN 设置 `AWS.WebIdentityCredentials` 对象：

```
AWS.config.credentials = new AWS.WebIdentityCredentials({
    RoleArn: 'arn:aws:iam::<AWS_ACCOUNT_ID>:role/<WEB_IDENTITY_ROLE_NAME>',
    ProviderId: 'graph.facebook.com|www.amazon.com', // Omit this for Google
    WebIdentityToken: ACCESS_TOKEN // Access token from identity provider
});
```

随后创建的服务对象将具有适当的凭证。在设置 `AWS.config.credentials` 属性之前创建的对象将不具有当前凭证。

您还可以在检索访问令牌之前创建 `AWS.WebIdentityCredentials`。这允许您在加载访问令牌之前创建依赖于凭证的服务对象。为此，请在不使用 `WebIdentityToken` 参数的情况下创建凭证对象：

```
AWS.config.credentials = new AWS.WebIdentityCredentials({
  RoleArn: 'arn:aws:iam::<AWS_ACCOUNT_ID>:role/<WEB_IDENTITY_ROLE_NAME>',
  ProviderId: 'graph.facebook.com|www.amazon.com' // Omit this for Google
});

// Create a service object
var s3 = new AWS.S3;
```

然后，在包含访问令牌的身份提供商开发工具包的回调中设置 `WebIdentityToken`：

```
AWS.config.credentials.params.WebIdentityToken = accessToken;
```

# Web 联合身份验证示例
<a name="config-web-identity-examples"></a>

以下是使用 Web 联合身份验证在浏览器 JavaScript 中获取凭证的几个示例。必须从 http:// 或 https:// 主机模式运行这些示例，以确保身份提供商可以重定向到您的应用程序。

## Login with Amazon 示例
<a name="config-web-identity-amazon-login-example"></a>

以下代码显示如何将 Login as Amazon 用作身份提供商。

```
<a href="#" id="login">
  <img border="0" alt="Login with Amazon"
    src="https://images-na.ssl-images-amazon.com/images/G/01/lwa/btnLWA_gold_156x32.png"
    width="156" height="32" />
</a>
<div id="amazon-root"></div>
<script type="text/javascript">
  var s3 = null;
  var clientId = 'amzn1.application-oa2-client.1234567890abcdef'; // client ID
  var roleArn = 'arn:aws:iam::<AWS_ACCOUNT_ID>:role/<WEB_IDENTITY_ROLE_NAME>';

  window.onAmazonLoginReady = function() {
    amazon.Login.setClientId(clientId); // set client ID

    document.getElementById('login').onclick = function() {
      amazon.Login.authorize({scope: 'profile'}, function(response) {
        if (!response.error) { // logged in
          AWS.config.credentials = new AWS.WebIdentityCredentials({
            RoleArn: roleArn,
            ProviderId: 'www.amazon.com',
            WebIdentityToken: response.access_token
          });

          s3 = new AWS.S3();

          console.log('You are now logged in.');
        } else {
          console.log('There was a problem logging you in.');
        }
      });
    };
  };

  (function(d) {
    var a = d.createElement('script'); a.type = 'text/javascript';
    a.async = true; a.id = 'amazon-login-sdk';
    a.src = 'https://api-cdn.amazon.com/sdk/login1.js';
    d.getElementById('amazon-root').appendChild(a);
  })(document);
</script>
```

## Facebook Login 示例
<a name="config-web-identity-facebook-login-example"></a>

以下代码显示如何将 Facebook Login 用作身份提供商：

```
<button id="login">Login</button>
<div id="fb-root"></div>
<script type="text/javascript">
var s3 = null;
var appId = '1234567890'; // Facebook app ID
var roleArn = 'arn:aws:iam::<AWS_ACCOUNT_ID>:role/<WEB_IDENTITY_ROLE_NAME>';

window.fbAsyncInit = function() {
  // init the FB JS SDK
  FB.init({appId: appId});

  document.getElementById('login').onclick = function() {
    FB.login(function (response) {
      if (response.authResponse) { // logged in
        AWS.config.credentials = new AWS.WebIdentityCredentials({
          RoleArn: roleArn,
          ProviderId: 'graph.facebook.com',
          WebIdentityToken: response.authResponse.accessToken
        });

        s3 = new AWS.S3;

        console.log('You are now logged in.');
      } else {
        console.log('There was a problem logging you in.');
      }
    });
  };
};

// Load the FB JS SDK asynchronously
(function(d, s, id){
   var js, fjs = d.getElementsByTagName(s)[0];
   if (d.getElementById(id)) {return;}
   js = d.createElement(s); js.id = id;
   js.src = "//connect.facebook.net/en_US/all.js";
   fjs.parentNode.insertBefore(js, fjs);
 }(document, 'script', 'facebook-jssdk'));
</script>
```

## Google\$1 Sign-in 示例
<a name="config-web-identity-google-login-example"></a>

以下代码显示如何将 Google\$1 Sign-in 用作身份提供商。用于来自 Google 的 Web 联合身份验证的访问令牌存储在 `response.id_token` 中，而不是像其他身份提供商一样存储在 `access_token` 中。

```
<span
  id="login"
  class="g-signin"
  data-height="short"
  data-callback="loginToGoogle"
  data-cookiepolicy="single_host_origin"
  data-requestvisibleactions="http://schemas.google.com/AddActivity"
  data-scope="https://www.googleapis.com/auth/plus.login">
</span>
<script type="text/javascript">
  var s3 = null;
  var clientID = '1234567890.apps.googleusercontent.com'; // Google client ID
  var roleArn = 'arn:aws:iam::<AWS_ACCOUNT_ID>:role/<WEB_IDENTITY_ROLE_NAME>';

  document.getElementById('login').setAttribute('data-clientid', clientID);
  function loginToGoogle(response) {
    if (!response.error) {
      AWS.config.credentials = new AWS.WebIdentityCredentials({
        RoleArn: roleArn, WebIdentityToken: response.id_token
      });

      s3 = new AWS.S3();

      console.log('You are now logged in.');
    } else {
      console.log('There was a problem logging you in.');
    }
  }

  (function() {
    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
    po.src = 'https://apis.google.com/js/client:plusone.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
  })();
 </script>
```