
# 使用APIG的APP认证和自定义认证实现API的双重认证
#### 应用场景
双重认证指用户根据业务需求自定义API认证策略，再结合APP认证/IAM认证，从而实现API的双重认证方式，保障API的安全性。本文以API前端认证使用APP认证和自定义认证结合场景为例，具体说明如何创建使用双重认证的API。
#### 方案优势
在API网关提供的安全认证模式下，用户可根据业务需求，灵活实现自定义认证，保障API的安全性。
#### 约束与限制
API网关支持的自定义认证依赖于函数工作流服务，创建自定义认证前，需要先创建函数。
#### 操作流程
![](https://support.huaweicloud.com/bestpractice-apig/zh-cn_image_0000002146573032.png)
1. [创建函数]
   创建自定义的前端函数，使用函数服务开发自定义认证。
   
2. [创建自定义认证]
   创建自定义认证，类型选择"前端"，函数地址选择上一步创建的函数。
   
3. [创建API]
   安全配置中的安全认证选择APP认证，并勾选"支持双重认证"，选择上一步创建的自定义认证。
   
4. [创建凭据]
   使用APP认证的API，需要在API网关中创建一个凭据，生成凭据ID和密钥对（Key、Secret）。
   
5. [绑定API]
   将创建的凭据绑定API后，才可以使用APP认证调用API。
   
6. [验证]
   调用API，验证双重认证是否设置成功。
   
 
#### 实施步骤
1. 登录[函数工作流控制台](https://console.huaweicloud.com/functiongraph/?locale=zh-cn)，在"总览"页面，单击"创建函数"。
   
   1. 根据下表，填写函数信息后，单击"创建函数"。
      表1函数信息配置 
      | 参数     | 配置说明                                                                                               |
      |:---|:---|
      | 选择创建方式 | 默认"创建空白函数"。                                                                                        |
      | 函数类型   | 默认"事件函数"。                                                                                          |
      | 区域     | 与API网关相同区域。                                                                                        |
      | 项目     | 华为云的区域默认对应一个项目，这个项目由系统预置，用来隔离物理区域间的资源（计算资源、存储资源和网络资源），以默认项目为单位进行授权，用户可以访问您账号中该区域的所有资源。此处默认为已选择的区域。 |
      | 函数名称   | 根据规划自定义名称。                                                                                         |
      | 企业项目   | 企业项目是项目的升级版，针对企业不同项目间资源的分组和管理，是逻辑隔离。此处默认"default"。                                                 |
      | 委托名称   | 用户委托函数工作流去访问其他的云服务。此处选择"未使用任何委托"。                                                                  |
      | 运行时    | 选择Python 3.9。                                                                                      |
         
      
   
   2. 函数创建完成后，进入函数详情。在"设置"页签的左侧导航栏中选择"环境变量"，根据下表参数说明，单击"编辑环境变量 \> 添加环境变量"。
      表2设置环境变量 
      | 参数   | 配置说明                                                                  |
      |:---|:---|
      | 键    | 环境变量的名称，此处添加"token"和"test"两个环境变量。token用于Header身份验证，test参数用于Query参数查询。 |
      | 值    | 环境变量的值，token值填写为"Basic dXNlcjE6cGFzc3dvcmQ="，test填写为"user@123"。       |
      | 加密参数 | 开启加密参数后，环境变量的值将以"\*"号加密显示，参数传输过程中键值也处于加密状态。对于敏感数据token值，开启加密参数选项。     |
         
      ![](https://support.huaweicloud.com/bestpractice-apig/zh-cn_image_0000002108775873.png "点击放大")
      
   
   3. 在"代码"页签，编辑自定义认证代码，将以下代码复制到index.py中。完成后，单击"部署代码"。代码编写请参考[创建用于前端自定义认证的函数](https://support.huaweicloud.com/usermanual-apig/apig_03_0069.html)。
      ```
      # -*- coding:utf-8 -*-
      import json
      def handler(event, context):
          testParameter = context.getUserData('test');
          userToken = context.getUserData('token');
          if event["headers"].get("token") == userToken and event["queryStringParameters"].get("test") == testParameter:
              resp = {
                  'statusCode': 200,
                  'body': json.dumps({
                      "status":"allow",
                      "context":{
                          "user":"auth success"
                      }
                  })
              }
          else:
              resp = {
                  'statusCode': 401,
                  'body': json.dumps({
                      "status":"deny",
                  })   
              }
          return json.dumps(resp)
      ```
      
   
   4. 配置测试事件并调试代码，然后部署。
      1. 在下拉框中选择"配置测试事件"并配置。将以下代码设置为测试事件。**测试事件的参数值与环境变量中的参数值需要保持一致。**
         ```
         {
             "headers": {
                 "token": "Basic dXNlcjE6cGFzc3dvcmQ="
             },
             "queryStringParameters": {
                 "test": "user@123"
             }   
         }
         ```
         ![](https://support.huaweicloud.com/bestpractice-apig/zh-cn_image_0000002181773945.png "点击放大")
         
         
      
      2. 创建测试事件完成后，单击"测试"调试代码。如下图，表示代码调试成功。 ![](https://support.huaweicloud.com/bestpractice-apig/zh-cn_image_0000002181852289.png "点击放大")
         
      
      3. 调试成功后，单击"部署代码"。
       
   
   
   
   
2. 进入API网关控制台页面，在左侧导航栏选择"API管理 \> API策略"。
   
   在"自定义认证"页签中，创建自定义认证。
   表3自定义认证配置 
   | 参数      | 配置说明                                                                           |
   |:---|:---|
   | 认证名称    | 根据规划自定义名称。                                                                     |
   | 类型      | 此处选择"前端"。                                                                      |
   | 函数地址    | 单击"添加"，选择[已创建函数]。 |
   | 版本或别名   | 默认"通过版本选择"。                                                                    |
   | 缓存时间(秒) | 30                                                                             |
   | 身份来源    | 第一个身份来源参数位置选择"Header"，参数名填写"token"；第二个身份来源参数位置选择"Query"，参数名填写"test"。           |
      
   
   
3. 在左侧导航栏选择"API管理 \> API列表"，单击"创建API \> 创建API"。
   
   1. 根据下表参数，配置前端信息。
      表4前端配置 
      | 参数     | 配置说明                                                                                                                                                                                                                                                                                                                                       |
      |:---|:---|
      | API名称  | 填写API名称。                                                                                                                                                                                                                                                                                                                                   |
      | 所属分组   | API所属分组，此处默认"DEFAULT"。                                                                                                                                                                                                                                                                                                                     |
      | URL    | 请求方法：接口调用方式，此处选择"GET"。 请求协议：选择API请求协议，此处选择"HTTPS"。 子域名：API分组创建后，系统为分组自动分配一个内部测试用的调试域名，此调试域名每天最多可以访问1000次。 路径：接口请求路径。此处填写"/api/two_factor_authorization"。 |
      | 网关响应   | API网关未能成功处理API请求，从而产生的错误响应。 默认的网关响应为"default"。                                                                                                                                                                                                                                  |
      | 安全认证   | 选择API认证方式，此处选择"APP认证"。                                                                                                                                                                                                                                                                                                                     |
      | 支持双重认证 | 勾选后，开启双重认证。选择[已创建自定义认证]。                                                                                                                                                                                                                                                                                 |
         
      
   
   2. 单击"下一步"，后端服务类型选择"Mock"。 选择Mock自定义返回码和填写Mock返回结果，单击"完成"。
      
   
   3. 发布API。
   
   
   
   
4. 在左侧导航栏选择"API管理 \> 凭据管理"，创建凭据。
   
   单击"创建凭据"，填写凭据名称后，单击"确定"。
   
   
5. 绑定API。
   
   单击凭据名称，进入凭据详情。在"关联API"区域，单击"绑定API"，选择API并单击"确定"。
   
   
6. 验证。
   
   - 您可以通过API网关的调试页面调用API，验证双重认证是否成功。 分别在Parameters和Headers中添加定义的test和token参数，参数值确保与自定义认证函数中的参数值一致，服务器返回200认证通过。如果请求参数与自定义认证函数不一致或参数错误，服务器返回401认证不通过。
     ![](https://support.huaweicloud.com/bestpractice-apig/zh-cn_image_0000002609553703.png "点击放大")
     
   
   - 您可以使用curl命令调用API，需要先下载JavaScript SDK。传入Key、Secret以及自定义的Header、Query等参数生成curl命令，然后将curl命令复制到命令行调用API，具体操作步骤请参考《API网关开发指南》中[curl](https://support.huaweicloud.com/devg-apig/apig-dev-180525061.html)。
     ![](https://support.huaweicloud.com/bestpractice-apig/zh-cn_image_0000002579194550.png "点击放大")
     
   
   
   
   
 
