

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 設定授權和身分驗證來保護 GraphQL APIs
<a name="security-authz"></a>

AWS AppSync 提供下列授權類型來保護 GraphQL APIs：API 金鑰、Lambda、IAM、OpenID Connect 和 Cognito 使用者集區。每個選項都提供不同的安全方法：

1. **API 金鑰授權**：控制未經驗證 APIs 的限流，提供簡單的安全選項。

1. **Lambda 授權**：啟用自訂授權邏輯，詳細說明函數輸入和輸出。

1. **IAM 授權**：使用 AWS簽章第 4 版簽署程序，透過 IAM 政策進行精細存取控制。

1. **OpenID Connect 授權**：整合 OIDC 相容服務以進行使用者身分驗證。

1. **Cognito 使用者集區**：使用 Cognito 的使用者管理功能實作群組型存取控制。

## 授權類型
<a name="authorization-types"></a>

您可以透過五種方式授權應用程式與您的 AWS AppSync GraphQL API 互動。您可以在 your AWS AppSync API 或 CLI 呼叫中指定下列其中一個授權類型值，以指定您使用的授權類型：
+   
** `API_KEY` **  
使用 API 金鑰。
+   
** `AWS_LAMBDA` **  
用於使用 AWS Lambda 函數。
+   
** `AWS_IAM` **  
適用於使用 AWS Identity and Access Management ([IAM](https://aws.amazon.com/iam/)) 許可。
+   
** `OPENID_CONNECT` **  
對於使用您的 OpenID Connect 提供者。
+   
** `AMAZON_COGNITO_USER_POOLS` **  
用於使用 Amazon Cognito 使用者集區。

這些基本授權類型適用於大多數的開發人員。如需更進階的使用案例，您可以透過 主控台、 CLI 和 新增其他授權模式 AWS CloudFormation。對於其他授權模式， AWS AppSync `API_KEY` `AWS_LAMBDA`提供採用上述值的授權類型 （即 、、`AWS_IAM`、 `OPENID_CONNECT`和 `AMAZON_COGNITO_USER_POOLS`)。

當您將 `API_KEY``AWS_LAMBDA`、 或 指定`AWS_IAM`為主要或預設授權類型時，您無法將其再次指定為其他授權模式之一。同樣地，您無法在`AWS_IAM`額外的授權模式中複製 `API_KEY``AWS_LAMBDA`或 。您可以使用多個 Amazon Cognito 使用者集區和 OpenID Connect 供應商。不過，您無法在預設授權模式和任何其他授權模式之間使用重複的 Amazon Cognito 使用者集區或 OpenID Connect 供應商。您可以使用對應的組態規則表達式，為您的 Amazon Cognito 使用者集區或 OpenID Connect 提供者指定不同的用戶端。

當您儲存 API 組態的變更時， 會 AWS AppSync 開始傳播變更。在您的組態變更傳播之前， 會 AWS AppSync 繼續提供先前組態的內容。傳播組態變更之後， 會 AWS AppSync 立即開始根據新組態提供內容。當 AWS AppSync 正在傳播 API 的變更時，我們無法根據先前的組態或新的組態來判斷 API 是否為您的內容提供服務。

## API\_KEY 授權
<a name="api-key-authorization"></a>

未驗證的 API 相較於已驗證 API 需要更嚴格的調節。其中一種控制未授權 GraphQL 端點調節的方法就是使用 API 金鑰。API 金鑰是應用程式中的硬式編碼值，會在您建立未經驗證的 GraphQL 端點時，由 AWS AppSync 服務產生。您可以從主控台、CLI 或 API [AWS AppSync 參考輪換 API](https://docs.aws.amazon.com/appsync/latest/APIReference/) 金鑰。

------
#### [ Console ]

1. 登入 AWS 管理主控台 並開啟 [AppSync 主控台](https://console.aws.amazon.com/appsync/)。

   1. 在 **APIs儀表板**中，選擇您的 GraphQL API。

   1. 在**側邊欄中**，選擇**設定**。

1. 在**預設授權模式下**，選擇 **API 金鑰**。

1. 在 **API 金鑰**表格中，選擇**新增 API 金鑰**。

   資料表中將產生新的 API 金鑰。

   1. 若要刪除舊的 API 金鑰，請在資料表中選取 API 金鑰，然後選擇**刪除**。

1. 選擇頁面底部的 **Save** (儲存)。

------
#### [ CLI ]

1. 如果您尚未這麼做，請設定您對 CLI AWS 的存取。如需詳細資訊，請參閱[組態基本概念](https://docs.aws.amazon.com//cli/latest/userguide/cli-configure-quickstart.html)。

1. 執行 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-graphql-api.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-graphql-api.html)命令來建立 GraphQL API 物件。

   您需要為此特定命令輸入兩個參數：

   1. GraphQL API `api-id`的 。

   1. 您 API `name`的新 。您可以使用相同的 `name`。

   1. `authentication-type`，這會是 `API_KEY`。
**注意**  
還有其他參數，例如 必須設定 `Region` ，但通常會預設為您的 CLI 組態值。

   範例命令可能如下所示：

   ```
   aws appsync update-graphql-api --api-id abcdefghijklmnopqrstuvwxyz --name TestAPI --authentication-type API_KEY
   ```

   輸出會在 CLI 中傳回。以下是 JSON 中的範例：

   ```
   {
       "graphqlApi": {
           "xrayEnabled": false,
           "name": "TestAPI",
           "authenticationType": "API_KEY",
           "tags": {},
           "apiId": "abcdefghijklmnopqrstuvwxyz",
           "uris": {
               "GRAPHQL": "https://s8i3kk3ufhe9034ujnv73r513e.appsync-api.us-west-2.amazonaws.com/graphql",
               "REALTIME": "wss://s8i3kk3ufhe9034ujnv73r513e.appsync-realtime-api.us-west-2.amazonaws.com/graphql"
           },
           "arn": "arn:aws:appsync:us-west-2:348581070237:apis/abcdefghijklmnopqrstuvwxyz"
       }
   }
   ```

------

API 金鑰可設定為最多 365 天，您可以從過期日開始再延展現有的過期日期的最多 365 天。用於開發目的或者需安全公開公用 API 時，建議使用 API 金鑰。

在用戶端上，由標題 `x-api-key` 指定 API 金鑰。

例如，如果您的 `API_KEY` 是 `'ABC123'`，您可以經由 `curl` 來傳送 GraphQL 查詢，如下所示：

```
$ curl -XPOST -H "Content-Type:application/graphql" -H "x-api-key:ABC123" -d '{ "query": "query { movies { id } }" }' https://YOURAPPSYNCENDPOINT/graphql
```

## AWS\_LAMBDA 授權
<a name="aws-lambda-authorization"></a>

您可以使用 AWS Lambda 函數實作自己的 API 授權邏輯。您可以對主要或次要授權方使用 Lambda 函數，但每個 API 可能只有一個 Lambda 授權函數。使用 Lambda 函數進行授權時，適用下列情況：
+ 如果 API 已啟用 `AWS_LAMBDA`和 `AWS_IAM`授權模式，則 SigV4 簽章無法用作`AWS_LAMBDA`授權字符。
+ 如果 API 已啟用 `AWS_LAMBDA`和 `OPENID_CONNECT`授權模式或 `AMAZON_COGNITO_USER_POOLS`授權模式，則無法使用 OIDC 權杖做為`AWS_LAMBDA`授權權杖。請注意，OIDC 權杖可以是承載結構描述。
+ Lambda 函數不得傳回解析程式超過 5MB 的內容資料。

例如，如果您的授權字符是 `'ABC123'`，您可以透過 curl 傳送 GraphQL 查詢，如下所示：

```
$ curl -XPOST -H "Content-Type:application/graphql" -H "Authorization:ABC123" -d '{ "query":
         "query { movies { id } }" }' https://YOURAPPSYNCENDPOINT/graphql
```

Lambda 函數會在每個查詢或變動之前呼叫。您可以根據 API ID 和身分驗證字符快取傳回值。當 Lambda 授權方回應小於 1，048，576 個位元組時， AWS AppSync 會快取後續請求的回應。如果 Lambda 授權方回應等於或大於 1，048，576 個位元組， AWS AppSync 不會快取回應，並為每個傳入請求叫用 Lambda 授權方。為了最佳化效能並將 Lambda 調用成本降至最低，建議您將 Lambda 授權方回應限制為 1，048，576 個位元組。根據預設，快取不會開啟，但可以在 API 層級或透過在函數的傳回`ttlOverride`值中設定值來啟用。

如有需要，可以指定在呼叫函數之前驗證授權字符的規則表達式。這些規則表達式用於驗證授權字符在呼叫函數之前格式是否正確。使用不符合此規則表達式的字符的任何請求將自動被拒絕。

用於授權的 Lambda 函數需要套用 的主體政策，以允許 `appsync.amazonaws.com` AWS AppSync 呼叫它們。此動作會在 AWS AppSync 主控台中自動完成； AWS AppSync 主控台*不會*移除政策。如需將政策連接至 Lambda 函數的詳細資訊，請參閱《 AWS Lambda 開發人員指南》中的以[資源為基礎的政策](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html#permissions-resource-serviceinvoke)。

您指定的 Lambda 函數將會收到具有下列形狀的事件：

```
{
    "authorizationToken": "ExampleAUTHtoken123123123",
    "requestContext": {
        "apiId": "aaaaaa123123123example123",
        "accountId": "111122223333",
        "requestId": "f4081827-1111-4444-5555-5cf4695f339f",
        "queryString": "mutation CreateEvent {...}\n\nquery MyQuery {...}\n",
        "operationName": "MyQuery",
        "variables": {}
    }
    "requestHeaders": {
        {{application request headers}}
    }
}
```

`event` 物件包含從應用程式用戶端傳送至之請求中的標頭 AWS AppSync。

授權函數必須至少傳回 `isAuthorized`，布林值指出請求是否已授權。 會 AWS AppSync 辨識從 Lambda 授權函數傳回的下列金鑰：

**注意**  
WebSocket 連線操作 `operationName`中 `requestContext` 的值由 設定為 AWS AppSync "`DeepDish:Connect`"。

### 函數清單
<a name="aws-lambda-authorization-list"></a>

`isAuthorized` （布林值，必要）  
布林值，指出 `authorizationToken` 中的值是否獲授權對 GraphQL API 進行呼叫。  
如果此值為 true，GraphQL API 的執行會繼續。如果此值為 false，`UnauthorizedException`則會引發

`deniedFields` （字串清單，選用）  
即使從解析程式傳回值`null`， 也會強制變更為 的清單。  
每個項目都是完整格式的欄位 ARN，格式為 `arn:aws:appsync:{{us-east-1}}:{{111122223333}}:apis/{{GraphQLApiId}}/types/{{TypeName}}/fields/{{FieldName}}`或簡短格式的 `{{TypeName}}.{{FieldName}}`。當兩個 APIs共用 Lambda 函數授權方，且兩個 APIs 之間的常見類型和欄位之間可能會有模棱兩可時，應使用完整的 ARN 表單。

`resolverContext` (JSON 物件，選用）  
在解析程式範本`$ctx.identity.resolverContext`中可見的 JSON 物件。例如，如果解析程式傳回下列結構：  

```
{
  "isAuthorized":true
  "resolverContext": {
    "banana":"very yellow",
    "apple":"very green" 
  }
}
```
解析程式範本`ctx.identity.resolverContext.apple`中的 值為 "`very green`"。`resolverContext` 物件僅支援鍵/值對。不支援巢狀金鑰。  
此 JSON 物件的總大小不得超過 5MB。

`ttlOverride` （整數，選用）  
應快取回應的秒數。如果未傳回任何值，則會使用來自 API 的值。如果這是 0，則不會快取回應。

Lambda 授權方的標準逾時為 10 秒，但在尖峰流量條件下可能會提早逾時。我們建議您設計在最短的時間內執行 函數 (1 秒以下），以擴展 API 的效能。

多個 AWS AppSync APIs可以共用單一身分驗證 Lambda 函數。不允許使用跨帳戶授權方。

在多個 APIs之間共用授權函數時，請注意，短格式欄位名稱 (`{{typename}}.{{fieldname}}`) 可能會不小心隱藏欄位。若要取消模糊 中的欄位`deniedFields`，您可以以 的形式指定不明確的欄位 ARN`arn:aws:appsync:{{region}}:{{accountId}}:apis/{{GraphQLApiId}}/types/{{typeName}}/fields/{{fieldName}}`。

若要在 中新增 Lambda 函數作為預設授權模式 AWS AppSync：

------
#### [ Console ]

1. 登入 AWS AppSync 主控台並導覽至您要更新的 API。

1. 導覽至 API 的設定頁面。

   將 API 層級授權變更為 **AWS Lambda**。

1. 選擇 AWS 區域 和 Lambda ARN 以授權 API 呼叫。
**注意**  
將自動新增適當的委託人政策， AWS AppSync 允許 呼叫您的 Lambda 函數。

1. 或者，設定回應 TTL 和字符驗證規則表達式。

------
#### [ AWS CLI ]

1. 將下列政策連接至正在使用的 Lambda 函數：

   ```
   aws lambda add-permission --function-name "{{my-function}}" --statement-id "appsync" --principal appsync.amazonaws.com --action lambda:InvokeFunction --output text 
   ```
**重要**  
如果您想要將函數的政策鎖定為單一 GraphQL API，您可以執行此命令：  

   ```
   aws lambda add-permission --function-name “{{my-function}}” --statement-id “appsync” --principal appsync.amazonaws.com --action lambda:InvokeFunction --source-arn “{{<my AppSync API ARN>}}” --output text
   ```

1. 更新您的 AWS AppSync API，以使用指定的 Lambda 函數 ARN 做為授權方：

   ```
   aws appsync update-graphql-api --api-id {{example2f0ur2oid7acexample}} --name {{exampleAPI}} --authentication-type AWS_LAMBDA --lambda-authorizer-config authorizerUri="{{arn:aws:lambda:us-east-2:111122223333:function:my-function}}"
   ```
**注意**  
您也可以包含其他組態選項，例如字符規則表達式。

------

下列範例說明 Lambda 函數，示範 Lambda 函數在用作 AWS AppSync 授權機制時可具有的各種身分驗證和失敗狀態：

```
def handler(event, context):
  # This is the authorization token passed by the client
  token = event.get('authorizationToken')
  # If a lambda authorizer throws an exception, it will be treated as unauthorized. 
  if 'Fail' in token:
    raise Exception('Purposefully thrown exception in Lambda Authorizer.')

  if 'Authorized' in token and 'ReturnContext' in token:
    return {
      'isAuthorized': True,
      'resolverContext': {
        'key': 'value'
      }
    }

  # Authorized with no f
  if 'Authorized' in token:
    return {
      'isAuthorized': True
    }
  # Partial authorization
  if 'Partial' in token:
    return {
      'isAuthorized': True,
      'deniedFields':['user.favoriteColor']
    }
  if 'NeverCache' in token:
    return {
      'isAuthorized': True,
      'ttlOverride': 0
    }
  if 'Unauthorized' in token:
    return {
      'isAuthorized': False
    }
  # if nothing is returned, then the authorization fails. 
  return {}
```

### 規避 SigV4 和 OIDC 權杖授權限制
<a name="aws-lambda-authorization-create-new-auth-token"></a>

下列方法可用來避免在特定授權模式啟用時，無法使用 SigV4 簽章或 OIDC 權杖做為 Lambda 授權權杖的問題。

如果您想要在為 AWS AppSync的 API 啟用 `AWS_IAM`和 授權模式時，使用 SigV4 簽章做為 Lambda `AWS_LAMBDA`授權字符，請執行下列動作：
+ 若要建立新的 Lambda 授權字符，請將隨機尾碼和/或字首新增至 SigV4 簽章。
+ 若要擷取原始 SigV4 簽章，請從 Lambda 授權字符中移除隨機字首和/或尾碼，以更新您的 Lambda 函數。然後，使用原始 SigV4 簽章進行身分驗證。

如果您想要在為 API 啟用授權模式或 `AMAZON_COGNITO_USER_POOLS`和 `AWS_LAMBDA` 授權模式時，使用 OIDC 權杖做為 Lambda AWS AppSync`OPENID_CONNECT`授權權杖，請執行下列動作：
+ 若要建立新的 Lambda 授權字符，請將隨機尾碼和/或字首新增至 OIDC 字符。Lambda 授權字符不應包含承載配置字首。
+ 若要擷取原始 OIDC 權杖，請從 Lambda 授權權杖中移除隨機字首和/或尾碼，以更新您的 Lambda 函數。然後，使用原始 OIDC 權杖進行身分驗證。

## AWS\_IAM 授權
<a name="aws-iam-authorization"></a>

此授權類型會在 [AWS GraphQL API 上強制執行簽章第 4 版簽署程序](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)。 GraphQL 您可以將身分與存取管理 ([IAM](https://aws.amazon.com/iam/)) 的存取政策與此授權類型建立關聯。您的應用程式可以使用 存取金鑰 （包含存取金鑰 ID 和私密存取金鑰） 或使用 Amazon Cognito 聯合身分提供的短期臨時登入資料來利用此關聯。

如果您希望角色擁有執行所有資料操作的存取權限：

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement": [
      {
         "Effect": "Allow",
         "Action": [
            "appsync:GraphQL"
         ],
         "Resource": [
            "arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/*"
         ]
      }
   ]
}
```

------

您可以從 AppSync 主控台的主要 API 列表頁面中找到 `YourGraphQLApiId`，就在您的 API 名稱下方。或者，您可以使用 CLI 來取得該資訊：`aws appsync list-graphql-apis`

如果您想要僅限制對於特定 GraphQL 操作的存取權限，您可以在根 `Query`、`Mutation` 以及 `Subscription` 欄位執行此操作。

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement": [
      {
         "Effect": "Allow",
         "Action": [
            "appsync:GraphQL"
         ],
         "Resource": [
            "arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/types/Query/fields/<Field-1>",
            "arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/types/Query/fields/<Field-2>",
            "arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/types/Mutation/fields/<Field-1>",
            "arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/types/Subscription/fields/<Field-1>"
         ]
     }
   ]
}
```

------

例如，假設您有以下結構描述且您想要限制取得所有文章的存取：

```
schema {
   query: Query
   mutation: Mutation
}

type Query {
   posts:[Post!]!
}

type Mutation {
   addPost(id:ID!, title:String!):Post!
}
```

角色的對應 IAM 政策 （例如，您可以連接到 Amazon Cognito 身分集區） 如下所示：

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
            "appsync:GraphQL"
            ],
            "Resource": [
                "arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/types/Query/fields/posts"
            ]
        }
    ]
}
```

------

## OPENID\_CONNECT 授權
<a name="openid-connect-authorization"></a>

此授權類型會強制執行 OIDC 相容服務提供的 [OpenID 連線](https://openid.net/specs/openid-connect-core-1_0.html) (OIDC) 權杖。您的應用程式可以運用由 OIDC 提供者定義的使用者與權限來控制存取權限。

發行者 URL 是您提供給 to AWS AppSync 的唯一必要組態值 （例如 `https://auth.example.com`)。此 URL 必須透過 HTTPS 定址。 AWS AppSync 會附加`/.well-known/openid-configuration`到發行者 URL，並根據 OpenID Connect Discovery `https://auth.example.com/.well-known/openid-configuration` 規格在 找到 OpenID 組態。 [OpenID ](https://openid.net/specs/openid-connect-discovery-1_0.html) 它預期會在此 URL 擷取相容於 [RFC5785](https://tools.ietf.org/html/rfc5785) 的 JSON 文件。此 JSON 文件必須包含`jwks_uri`金鑰，該金鑰指向具有簽署金鑰的 JSON Web Key Set (JWKS) 文件。 AWS AppSync 要求 JWKS 包含 `kty`和 的 JSON 欄位`kid`。

AWS AppSync 支援各種簽署演算法。


| 簽署演算法 | 
| --- | 
| RS256 | 
| RS384 | 
| RS512 | 
| PS256 | 
| PS384 | 
| PS512 | 
| HS256 | 
| HS384 | 
| HS512 | 
| ES256 | 
| ES384 | 
| ES512 | 

我們建議您使用 RSA 演算法。由提供者發行的字符必須包含字符發行的時間 (`iat`)，且可包含驗證時的時間 (`auth_time`)。您可以提供 OpenID Connect 組態中的發行時間的 TTL 值 (`iatTTL`) 和身分驗證時間 (`authTTL`)，以供額外驗證。如果您的提供者授權多個應用程式，您也可以提供用於根據用戶端 ID 授權的一般表達式 (`clientId`)。當 OpenID Connect 組態中有 `clientId` 時， AWS AppSync 會要求 與字符中的 `aud`或 宣告相符`clientId`，以驗證`azp`宣告。

若要驗證多個用戶端 IDs請使用管道運算子 (「\|」)，這是規則表達式中的「或」。例如，如果您的 OIDC 應用程式有四個用戶端具有用戶端 IDs，例如 0A1S2D、1F4G9H、1J6L4B、6GS5MG，只要驗證前三個用戶端 IDs，您會在用戶端 ID 欄位中放置 1F4G9H\|1J6L4B\|6GS5MG。

如果 API 設定了多種授權類型， AWS AppSync 會將其與 API 組態中指定的發行者 URL 進行比較，以驗證來自請求標頭的 JWT 字符中存在的發行者 (iss 宣告）。不過，當 API 只設定 OPENID\_CONNECT 授權時， AWS AppSync 會略過此發行者 URL 驗證步驟。

## AMAZON\_COGNITO\_USER\_POOLS 授權
<a name="amazon-cognito-user-pools-authorization"></a>

此授權類型會強制執行 Amazon Cognito 使用者集區提供的 OIDC 權杖。您的應用程式可以利用來自另一個 AWS 帳戶的使用者集區和使用者集區中的使用者和群組，並將其與 GraphQL 欄位建立關聯，以控制存取。

使用 Amazon Cognito 使用者集區時，您可以建立使用者所屬的群組。此資訊以 JWT 權杖進行編碼，您的應用程式會在傳送 GraphQL 操作時，以授權標頭傳送至 AWS AppSync。您可以使用結構描述上的 GraphQL 指令來控制哪些群組可以叫用欄位上的哪些解析程式，進而為您的客戶提供更具控制性的存取權限。

例如，假設您有下列 GraphQL 結構描述：

```
schema {
   query: Query
   mutation: Mutation
}

type Query {
   posts:[Post!]!
}

type Mutation {
   addPost(id:ID!, title:String!):Post!
}
...
```

如果您在 Amazon Cognito 使用者集區中有兩個群組 - 部落客和讀者 - 而且您想要限制讀者，讓他們無法新增項目，則結構描述應該如下所示：

```
schema {
   query: Query
   mutation: Mutation
}
```

```
type Query {
   posts:[Post!]!
   @aws_auth(cognito_groups: ["Bloggers", "Readers"])
}

type Mutation {
   addPost(id:ID!, title:String!):Post!
   @aws_auth(cognito_groups: ["Bloggers"])
}
...
```

請注意，如果您想要將存取權限預設為特定授予或拒絕授予策略，您可以省略 `@aws_auth` 指令。在透過主控台或以下 CLI 命令建立 GraphQL API 時，您可以在使用者集區組態中指定授予或拒絕授予策略：

```
$ aws appsync --region us-west-2 create-graphql-api --authentication-type AMAZON_COGNITO_USER_POOLS  --name userpoolstest --user-pool-config '{ "userPoolId":"test", "defaultEffect":"ALLOW", "awsRegion":"us-west-2"}'
```

## 使用其他授權模式
<a name="using-additional-authorization-modes"></a>

當您新增其他授權模式時，您可以直接在 AWS AppSync GraphQL API 層級設定授權設定 （即您可以直接在`GraphqlApi`物件上設定`authenticationType`的欄位），並在結構描述上做為預設值。這表示沒有特定指示詞的任何類型必須傳遞 API 層級授權設定。

在結構描述層級上，您可以在結構描述上使用指示詞來指定其他授權模式。您可以在結構描述中的個別欄位上指定授權模式。例如，針對 `API_KEY` 授權，您可以在結構描述物件類型定義/欄位上使用 `@aws_api_key`。結構描述欄位和物件類型定義支援下列指示詞：
+  `@aws_api_key` - 指定欄位會經由 `API_KEY` 授權。
+  `@aws_iam` - 指定欄位會經由 `AWS_IAM` 授權。
+  `@aws_oidc` - 指定欄位會經由 `OPENID_CONNECT` 授權。
+  `@aws_cognito_user_pools` - 指定欄位會經由 `AMAZON_COGNITO_USER_POOLS` 授權。
+  `@aws_lambda` - 指定欄位會經由 `AWS_LAMBDA` 授權。

您無法將 `@aws_auth` 指示詞搭配使用其他授權模式。`@aws_auth` 只能在沒有其他授權模式的 `AMAZON_COGNITO_USER_POOLS` 授權內容中運作。但是，您可以搭配相同的引數，使用 `@aws_cognito_user_pools` 指示詞來取代 `@aws_auth` 指示詞。這兩者的主要差異是您可以在任何欄位和物件類型定義上指定 `@aws_cognito_user_pools`。

為了了解其他授權模式如何運作以及如何在結構描述上指定這些模式，讓我們看看以下結構描述：

```
schema {
   query: Query
   mutation: Mutation
}

type Query {
   getPost(id: ID): Post
   getAllPosts(): [Post]
   @aws_api_key
}

type Mutation {
   addPost(
      id: ID!
      author: String!
      title: String!
      content: String!
      url: String!
   ): Post!
}

type Post @aws_api_key @aws_iam {
   id: ID!
   author: String
   title: String
   content: String
   url: String
   ups: Int!
   downs: Int!
   version: Int!
}
...
```

對於此結構描述，假設 `AWS_IAM`是 AWS AppSync GraphQL API 上的預設授權類型。這表示沒有指示詞的欄位會使用 `AWS_IAM` 進行保護。例如，`Query` 類型的 `getPost` 欄位就是這種情況。結構描述指示詞可讓您使用超過一種授權模式。例如，您可以在 AWS AppSync GraphQL API 上將 `API_KEY` 設定為額外的授權模式，而且您可以使用 `@aws_api_key`指令來標記欄位 （例如，在此範例中`getAllPosts`)。指示詞會在欄位層級運作，因此您也需要將 `API_KEY` 存取權限提供給 `Post` 類型。您可以透過在 `Post` 類型中使用指示詞標記每個欄位，或是使用 `@aws_api_key` 指示詞標記 `Post` 類型，來執行此作業。

若要進一步限制對 `Post` 類型中欄位的存取，您可以針對 `Post` 類型中的個別欄位使用指示詞，如下所示。

例如，您可以將 `restrictedContent` 欄位新增到 `Post` 類型，並使用 `@aws_iam` 指示詞限制對該項目進行存取。`AWS_IAM` 已驗證請求可以存取 `restrictedContent`，但 `API_KEY` 請求將無法存取它。

```
type Post @aws_api_key @aws_iam{
   id: ID!
   author: String
   title: String
   content: String
   url: String
   ups: Int!
   downs: Int!
   version: Int!
   restrictedContent: String!
   @aws_iam
}
...
```

## 精細定義存取控制
<a name="fine-grained-access-control"></a>

上述資訊示範了如何限制存取權限，或將存取權限授予特定 GraphQL 欄位。若您希望根據特定條件設定資料的存取控制 (例如根據進行呼叫的使用者，以及使用者是否擁有資料)，您可以在解析程式中使用映射範本。您也可以執行更複雜的商業邏輯；我們會在[篩選資訊](#aws-appsync-filtering-information)中進行說明。

本節說明如何使用 DynamoDB 解析程式映射範本來設定資料的存取控制。

在繼續之前，如果您不熟悉 AWS AppSync 中的映射範本，建議您檢閱 DynamoDB 的[解析程式映射範本參考](resolver-mapping-template-reference.md#aws-appsync-resolver-mapping-template-reference)和解析程式映射範本參考。 [ DynamoDB](resolver-mapping-template-reference-dynamodb.md#aws-appsync-resolver-mapping-template-reference-dynamodb)

在下列使用 DynamoDB 的範例中，假設您使用上述部落格文章結構描述，並且僅允許建立文章的使用者編輯它。評估程序需使用者獲得應用程式的登入資料，例如使用 Amazon Cognito 使用者集區，然後將這些登入資料做為 GraphQL 操作的一部分。映射範本接著將取代在條件式陳述式中的登入資料值 (例如使用者名稱)，此資訊接著將與資料庫中的值進行比較。

![顯示字符擷取、請求傳送、條件式檢查和操作執行的四步驟工作流程。](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/FGAC.png)


若要新增此功能，請新增 `editPost` 的 GraphQL 欄位，如下所示：

```
schema {
   query: Query
   mutation: Mutation
}

type Query {
   posts:[Post!]!
}

type Mutation {
   editPost(id:ID!, title:String, content:String):Post
   addPost(id:ID!, title:String!):Post!
}
...
```

`editPost` 的解析程式映射範本 (顯示於本區段末端的範例中) 需要針對您的資料存放區執行邏輯檢查，只允許建立文章的使用者可對其進行編輯。由於這是編輯操作，因此會對應至 DynamoDB `UpdateItem`中的 。在執行此動作前可以使用透過使用者身分驗證傳遞的上下文來執行條件檢查。此資訊存放在 `Identity` 物件中，有以下值：

```
{
   "accountId" : "12321434323",
   "cognitoIdentityPoolId" : "",
   "cognitoIdentityId" : "",
   "sourceIP" : "",
   "caller" : "ThisistheprincipalARN",
   "username" : "username",
   "userArn" : "Sameasabove"
}
```

若要在 DynamoDB`UpdateItem` 呼叫中使用此物件，您需要將使用者身分資訊存放在資料表中以進行比較。首先，您的 `addPost` 變動需要儲存建立者。其次，您的 `editPost` 變動需在更新前執行條件式檢查。

以下是將使用者身分`addPost`儲存為 `Author`欄的解析程式程式碼範例：

```
import { util, Context } from '@aws-appsync/utils';
import { put } from '@aws-appsync/utils/dynamodb';

export function request(ctx) {
	const { id: postId, ...item } = ctx.args;
	return put({
		key: { postId },
		item: { ...item, Author: ctx.identity.username },
		condition: { postId: { attributeExists: false } },
	});
}

export const response = (ctx) => ctx.result;
```

請注意，`Author` 屬性從來自於應用程式的 `Identity` 物件發布。

最後，以下是 的解析程式程式碼範例`editPost`，只有在請求來自建立文章的使用者時，才會更新部落格文章的內容：

```
import { util, Context } from '@aws-appsync/utils';
import { put } from '@aws-appsync/utils/dynamodb';

export function request(ctx) {
	const { id, ...item } = ctx.args;
	return put({
		key: { id },
		item,
		condition: { author: { contains: ctx.identity.username } },
	});
}

export const response = (ctx) => ctx.result;
```

此範例使用覆寫所有值`PutItem`的 ，而不是 `UpdateItem`，但相同的概念適用於`condition`陳述式區塊。

## 篩選資訊
<a name="aws-appsync-filtering-information"></a>

在某些情況下，您無法控制資料來源的回應，但又不想在成功寫入或讀取資料來源時，將不必要的資訊傳送給用戶端。如果發生這些情況，您可以使用回應映射範本來篩選資訊。

例如，假設您的部落格文章 DynamoDB 資料表上沒有適當的索引 （例如 上的索引`Author`)。您可以使用下列解析程式：

```
import { util, Context } from '@aws-appsync/utils';
import { get } from '@aws-appsync/utils/dynamodb';

export function request(ctx) {
	return get({ key: { ctx.args.id } });
}

export function response(ctx) {
	if (ctx.result.author === ctx.identity.username) {
		return ctx.result;
	}
	return null;
}
```

即使呼叫者不是建立文章的作者，請求處理常式也會擷取項目。為了防止傳回所有資料，回應處理常式會檢查以確保呼叫者符合項目的作者。如果發起人不符合此檢查，只會傳回 nul在某些情況下，您無法控制數據源的響應，但又不想在成功寫入或讀取數據源時將不必要的信息發送給客戶端。l 回應。

## 資料來源存取
<a name="data-source-access"></a>

AWS AppSync 會使用 Identity and Access Management ([IAM](https://aws.amazon.com/iam/)) 角色和存取政策與資料來源通訊。如果您使用現有角色，則需要新增信任政策， AWS AppSync 才能擔任該角色。信任關係如下所示：

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "appsync.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
```

------

縮小角色的存取政策範圍，使其只能對必要的最少資源集合採取行動，是非常重要的。當使用 AppSync 主控台來建立資料來源並建立角色時，將會為您自動完成這些動作。不過，從 IAM 主控台使用內建範例範本在 AWS AppSync 主控台外部建立角色時，許可不會自動縮小資源的範圍，您應該在將應用程式移至生產環境之前執行此動作。