# 通过API KEY认证访问在线服务
如果在线服务的状态处于"运行中"，则表示在线服务已部署成功。部署成功的在线服务，将为用户提供一个可调用的API，此API为标准RESTful API。在使用ModelArts提供的在线服务时，用户需要通过API调用进行模型预测，通常需要进行身份认证以确保安全。然而，传统的认证方式可能需要复杂的配置和管理，增加了开发和维护的难度。如何在保证安全的前提下，简化API调用的认证流程？ModelArts支持使用API KEY认证方式访问在线服务。
在向在线服务发起预测请求时，需要提前获取API KEY，在请求头中添加认证信息。API KEY是通过API密钥进行API调用时的认证。API KEY是每个用户单独的身份认证，是个人调用应用接口的依据，必须妥善保管。API KEY认证适用于需要简单认证的场景，只要有用API KEY凭据的用户都可以访问在线服务。
在将在线服务RESTful API集成至生产环境之前，需要对此API进行调测，您可以使用以下方式通过API KEY认证向在线服务发起预测请求：
- [方式一：使用图形界面的软件进行预测（以Postman为例）]。Windows系统建议使用Postman。
- [方式二：使用curl命令发送预测请求]。Linux系统建议使用curl命令。
- [方式三：使用Python语言发送预测请求]。
- [方式四：使用Java语言发送预测请求]。
#### 权限说明
表1API KEY功能所需权限。 
| 权限名          | action                  | 使用场景         |
|:---|:---|:---|
| 查询模型服务列表    | modelarts:service:list  | 查询模型服务列表     |
| 获取API KEY列表 | modelarts:apikey:list    | 访问API KEY列表 |
| 解绑API KEY    | modelarts:apikey:unbind   | 解绑API KEY    |
| 创建API KEY  | modelarts:apikey:create | 创建API KEY  |
| 绑定API KEY   | modelarts:apikey:bind    | 绑定API KEY  |
| 删除API KEY  | modelarts:apikey:delete  | 删除API KEY   |
   
#### 前提条件
- [配置服务信息](https://support.huaweicloud.com/inference-modelarts/inference2.0-modelarts-0016.html)时认证方式选择"API KEY认证"。
- 调用API时请求并发量、请求体大小以及请求超时时间需小于等于部署时的设定值，否则会导致请求失败。
  图1在线服务部署API KEY认证方式配置示例   
  ![](https://support.huaweicloud.com/inference-modelarts/figure/zh-cn_image_0000002623239787.png)
  
  
 
#### 约束限制
默认单个账号（不是IAM子用户）最大可以创建100个API Key。如果要扩大创建数量，需要提工单申请。
 #### 管理API Key
如果您需要使用支持API Key认证功能，需要您在部署在线服务之前进行授权管理操作完成API Key的创建，并绑定在线服务。在"模型推理 \> 在线推理"页面您可以实现API Key的创建和管理，包括创建、删除、绑定在线服务和解绑在线服务。
- 创建API Key
  1. 登录[ModelArts管理控制台](https://console.huaweicloud.com/modelarts/)，在左侧导航栏中选择"模型推理 \> 在线推理"，默认进入"在线推理"列表。
  
  2. 单击"API Key授权管理"，切换到"API Key授权管理"页签，单击"创建API Key"。
  
  3. 在"创建API Key"弹框中，按[表2]填写API Key信息，单击"确定"。
     创建API Key后，系统自动触发下载，后续暂不支持手动下载，请妥善保管。
      表2API Key参数说明 
     | 参数     | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                |
     |:---|:---|
     | 名称      | 自定义API Key名称。名称具有唯一性，不可重复。                                                                                                                                                                                                                                                                                                                                                                                                         |
     | 描述（可选） | 自定义API Key的描述。                                                                                                                                                                                                                                                                                                                                                                                                                  |
     | 授权范围     | API Key生效范围。 - 全部在线服务：授权当前工作空间的全部在线服务。  - 指定在线服务：授权当前工作空间的指定在线服务。在创建后需要在API Key授权管理页面[API KEY绑定服务]后才会生效，使用时可以使用绑定的API Key调用对应的在线服务。   |
        
     图2创建API Key   
     ![](https://support.huaweicloud.com/inference-modelarts/figure/zh-cn_image_0000002685598171.png)
     
     
   
- API Key绑定服务
  创建API Key时，如果生效范围为指定在线服务，则创建API Key后需要在授权管理页面绑定在线服务，API Key才会生效。只支持绑定认证方式为API Key，且服务状态为运行中、告警、停止中、停止或异常的服务。
  1. 登录[ModelArts管理控制台](https://console.huaweicloud.com/modelarts/)，在左侧导航栏中选择"模型推理 \> 在线推理"，默认进入"在线推理"列表。
  
  2. 单击"API Key授权管理"，切换到"API Key授权管理"页签。
  
  3. 单击待绑定在线服务的API Key操作列的"绑定"。
  
  4. 在"绑定服务"弹框中，勾选当前API Key要绑定的服务，单击"确定"。 即可对当前API Key绑定在线服务，访问该被绑定的在线服务时，可以使用对应的API Key调用绑定的在线服务。
     
     
   
- API Key解绑服务 如果API Key生效范围为指定在线服务，想要切换API Key所绑定的在线服务，也可以对已绑定服务的API Key进行解绑。
  1. 登录ModelArts管理控制台，在左侧导航栏中选择"模型推理 \> 在线推理"，默认进入"在线推理"列表。
  
  2. 单击"API Key授权管理"，切换到"API Key授权管理"页签。
  
  3. 单击待解绑在线服务的API Key操作列的"解绑"。
  
  4. 在解绑服务弹框中，勾选当前API Key要解绑的服务，单击"确定"。
     图3API Key解绑服务   
     ![](https://support.huaweicloud.com/inference-modelarts/figure/zh-cn_image_0000002612096945.png)
     
     
   
- 删除API Key 如果API Key无业务需求，也可以删除API Key。如果API Key生效范围为指定在线服务，当API Key有绑定在线服务，不支持删除API Key。
  1. 登录ModelArts管理控制台，在左侧导航栏中选择"模型推理 \> 在线推理"，默认进入"在线推理"列表。
  
  2. 单击"API Key授权管理"，切换到"API Key授权管理"页签。
  
  3. 单击待删除API Key操作列的"删除"。
  
  4. 在"删除API Key"弹框中，一键输入DELETE，单击"确定"。
   
 
 #### 获取服务调用信息
在调用服务前，需要**[创建API KEY]** 且**该API KEY[已绑定待访问的在线服务]** ，获取**预测文件的本地路径** 、**在线服务的调用地址** 和**在线服务的输入参数**信息。
- **获取API KEY内容**：打开创建API KEY后自动下载的csv文件，打开文件后可看到api_key字段就是具体的API KEY内容。
- **预测文件的本地路径**：可使用绝对路径（如Windows格式"D:/test.png"，Linux格式"/opt/data/test.png"），也可以使用相对路径（如"./test.png"）。
- **在线服务的调用地址和输入参数信息** ：可以在控制台的"模型推理 \> 在线推理"，单击指定在线服务，在服务"基本信息"页签的"调用信息"获取。
  "调用URL"即在线服务的调用地址。当模型配置文件中apis定义了路径，调用地址后需拼接自定义路径。如："{在线服务的调用地址}/v1/chat/completions"。
  
  
  
 
 #### 方式一：使用图形界面的软件进行预测（以Postman为例）
1. 下载Postman软件并安装，您也可以直接在Chrome浏览器添加Postman扩展程序（也可使用其他支持发送post请求的软件）。Postman推荐使用8.11.1版本。
2. 打开Postman，如[图4]所示。
   图4Postman界面
   ![](https://support.huaweicloud.com/inference-modelarts/figure/zh-cn_image_0000002581268620.png)
   
3. 在Postman界面填写参数，以图像分类举例说明。
   - 选择POST任务，将在线服务的调用地址复制到POST后面的方框。Headers页签的Key值填写为"Authorization"，Value值为"Bearer"加空格加API KEY的内容。
     图5参数填写
     ![](https://support.huaweicloud.com/inference-modelarts/figure/zh-cn_image_0000002611828371.png)
     
   
   - 在Body页签，根据模型的输入参数不同，可分为2种类型：文件输入、文本输入。
     - **文件输入**
       选择"form-data"。在"KEY"值填写模型的入参，和在线服务的输入参数对应，比如本例中预测图片的参数为"images"。然后在"VALUE"值，选择文件，上传一张待预测图片（当前仅支持单张图片预测），如[图6]所示。
       图6填写Body   
       ![](https://support.huaweicloud.com/inference-modelarts/figure/zh-cn_image_0000002611828369.png)
       
       
     
     - **文本输入**
       选择"raw"，选择JSON(application/json)类型，在下方文本框中填写请求体，请求体格式与内容与用户部署模型相关，平台不做任何处理。
       图7在线服务iam认证，文本请求示意图   
       ![](https://support.huaweicloud.com/inference-modelarts/figure/zh-cn_image_0000002581428526.png)
       
       请求体样例如下：
       ```
       {
           "model": "test",
           "messages": [
               {
                   "role": "user",
                   "content": "你是谁？"
               }
           ],
           "max_tokens": 100,
           "top_k": -1,
           "top_p": 1,
           "temperature": 0,
           "ignore_eos": false,
           "stream": false
       }
       ```
       
       
      
    
4. 参数填写完成，单击"send"发送请求，结果会在"Response"下的对话框里显示。
   - 文件输入形式的预测结果样例如[图8]所示，返回结果的字段值根据不同模型可能有所不同。
   
   - 文本输入形式的预测结果样例如[图9]所示，具体返回内容与格式与用户部署模型相关。
     图8文件输入预测结果
     ![](https://support.huaweicloud.com/inference-modelarts/figure/zh-cn_image_0000002581428528.png)
     
     图9文本输入预测结果
     ![](https://support.huaweicloud.com/inference-modelarts/figure/zh-cn_image_0000002611828367.png)
     
     
    
 
 #### 方式二：使用curl命令发送预测请求
使用curl命令发送预测请求的命令格式也分为文件输入、文本输入两类。
- 文件输入
  ```
  curl -kv -F 'images=@图片路径' -H 'Authorization:Bearer API-KEY内容' -X POST 在线服务地址
  ```
  - "-k"是指允许不使用证书访问SSL站点。
  
  - "-F"是指上传数据的是文件，本例中参数名为"images"，这个名字可以根据具体情况变化，@后面是图片的存储路径。
  
  - "-H"是post命令的headers，Headers的Key值为"Authorization"，这个名字为固定的， API-KEY内容是API KEY的内容。
  
  - "POST"后面跟随的是在线服务的调用地址。
  
  
  curl命令文件输入样例：
  ```
  curl -kv -F 'images=@/home/data/test.png' -H 'Authorization:Bearer 4**************w' -X POST https://{{infer-endpoint}}/v2/infers/eb3e0c54-3dfa-4750-af0c-95c45e5d3e83
  ```
  
- 文本输入
  ```
  curl -kv -d '{"data":{"req_data":[{"sepal_length":3,"sepal_width":1,"petal_length":2.2,"petal_width":4}]}}' -H 'Authorization:Bearer 4**************w' -H 'Content-type: application/json' -X POST https://{{infer-endpoint}}/v2/infers/eb3e0c54-3dfa-4750-af0c-95c45e5d3e83
  ```
  "-d"是Body体的文本内容。
  
 
 #### 方式三：使用Python语言发送预测请求
1. 下载Python SDK并在开发工具中完成SDK配置。具体操作请参见[在Python环境中集成API请求签名的SDK](https://support.huaweicloud.com/devg-apisign/api-sign-sdk-python.html)。
2. 创建请求体，进行预测请求。
   - **输入为文件格式**
     ```
     # coding=utf-8
     import requests
     if __name__ == '__main__':
         # Config url, token and file path.
         url = "在线服务的调用地址"
         api_key= "API KEY内容"
         file_path = "预测文件的本地路径"
         # Send request.
         headers = {
             'Authorization': 'Bearer ' + api_key
         }
         files = {
             'images': open(file_path, 'rb')
         }
         resp = requests.post(url, headers=headers, files=files)
         # Print result.
         print(resp.status_code)
         print(resp.text)
     ```
     "files"中的参数名由在线服务的输入参数决定，需要和"类型"为"file"的输入参数"名称"保持一致。以[获取服务调用信息]里获取的文件预测输入参数"images"为例。
     
   
   - **输入为文本格式（json类型）**
     读取本地预测文件并进行base64编码的请求体示例如下：
     ```
     # coding=utf-8
     import base64
     import requests
     if __name__ == '__main__':
         # Config url, token and file path
         url = "在线服务的调用地址"
         api_key= "API KEY内容"
         file_path = "预测文件的本地路径"
         with open(file_path, "rb") as file:
             base64_data = base64.b64encode(file.read()).decode("utf-8")
         # Set body,then send request
         headers = {
             'Content-Type': 'application/json',
             'Authorization': 'Bearer ' + api_key
         }
         body = {
             'image': base64_data
         }
         resp = requests.post(url, headers=headers, json=body)
         # Print result
         print(resp.status_code)
         print(resp.text)
     ```
     "body"中的参数名由在线服务的输入参数决定，需要和"类型"为"string"的输入参数"名称"保持一致。以[获取服务调用信息]里获取的文本预测输入参数"image"为例。"body"中的base64_data值为string类型。
     
    
 
 #### 方式四：使用Java语言发送预测请求
1. 下载Java SDK并在开发工具中完成SDK配置。具体操作请参见[在Java环境中集成API请求签名的SDK](https://support.huaweicloud.com/devg-apisign/api-sign-sdk-java.html)。
2. （可选）当预测请求的输入为文件格式时，Java工程依赖httpmime模块。
   1. 在工程"libs"中增加httpmime-x.x.x.jar。完整的Java依赖库如[图10]所示。
      httpmime-x.x.x.jar建议使用4.5及以上版本，下载地址：<https://mvnrepository.com/artifact/org.apache.httpcomponents/httpmime>。
      图10Java依赖库   
      ![](https://support.huaweicloud.com/inference-modelarts/figure/zh-cn_image_0000002581268614.png) 
   
   2. httpmime-x.x.x.jar添加完成后，在Java工程的.classpath文件中，补充httpmime信息，如下所示：
      ```
      <?xml version="1.0" encoding="UTF-8"?>
      <classpath>
      <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
      <classpathentry kind="src" path="src"/>
      <classpathentry kind="lib" path="libs/commons-codec-1.11.jar"/>
      <classpathentry kind="lib" path="libs/commons-logging-1.2.jar"/>
      <classpathentry kind="lib" path="libs/httpclient-4.5.13.jar"/>
      <classpathentry kind="lib" path="libs/httpcore-4.4.13.jar"/>
      <classpathentry kind="lib" path="libs/httpmime-x.x.x.jar"/>
      <classpathentry kind="lib" path="libs/java-sdk-core-3.1.2.jar"/>
      <classpathentry kind="lib" path="libs/okhttp-3.14.9.jar"/>
      <classpathentry kind="lib" path="libs/okio-1.17.2.jar"/>
      <classpathentry kind="output" path="bin"/>
      </classpath>
      ```
      
    
3. 创建Java类，进行预测请求。
   - **输入为文件格式**
     Java的请求体示例如下：
     ```
     // Package name of the demo.
     package com.apig.sdk.demo;
     import org.apache.http.Consts;
     import org.apache.http.HttpEntity;
     import org.apache.http.client.methods.CloseableHttpResponse;
     import org.apache.http.client.methods.HttpPost;
     import org.apache.http.entity.ContentType;
     import org.apache.http.entity.mime.MultipartEntityBuilder;
     import org.apache.http.impl.client.HttpClients;
     import org.apache.http.util.EntityUtils;
     import java.io.File;
     public class MyTokenFile {
         public static void main(String[] args) {
             // Config url, token and filePath
             String url = "在线服务的调用地址";
             String apiKey = "API KEY内容";
             String filePath = "预测文件的本地路径";
             try {
                 // Create post
                 HttpPost httpPost = new HttpPost(url);
                 // Add header parameters
                 httpPost.setHeader("Authorization", "Bearer " + api_key);
                 // Add a body if you have specified the PUT or POST method. Special characters, such as the double quotation mark ("), contained in the body must be escaped.
                 File file = new File(filePath);
                 HttpEntity entity = MultipartEntityBuilder.create().addBinaryBody("images", file).setContentType(ContentType.MULTIPART_FORM_DATA).setCharset(Consts.UTF_8).build();
                 httpPost.setEntity(entity);
                 // Send post
                 CloseableHttpResponse response = HttpClients.createDefault().execute(httpPost);
                 // Print result
                 System.out.println(response.getStatusLine().getStatusCode());
                 System.out.println(EntityUtils.toString(response.getEntity()));
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
     }
     ```
     "addBinaryBody"中的参数名由在线服务的输入参数决定，需要和"类型"为"file"的输入参数"名称"保持一致。此处以[获取服务调用信息]里获取的"images"为例。
     
   
   - **输入为文本格式（json类型）**
     读取本地预测文件并进行base64编码的请求体示例如下：
     ```
     // Package name of the demo.
     package com.apig.sdk.demo;
     import org.apache.http.HttpHeaders;
     import org.apache.http.client.methods.CloseableHttpResponse;
     import org.apache.http.client.methods.HttpPost;
     import org.apache.http.entity.StringEntity;
     import org.apache.http.impl.client.HttpClients;
     import org.apache.http.util.EntityUtils;
     public class MyTokenTest {
         public static void main(String[] args) {
             // Config url, token and body
             String url = "在线服务的调用地址";
             String apiKey = "API KEY内容";
             String body = "{}";
             try {
                 // Create post
                 HttpPost httpPost = new HttpPost(url);
                 // Add header parameters
                 httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
                 httpPost.setHeader("Authorization", "Bearer " + api_key);
                 // Special characters, such as the double quotation mark ("), contained in the body must be escaped.
                 httpPost.setEntity(new StringEntity(body));
                 // Send post.
                 CloseableHttpResponse response = HttpClients.createDefault().execute(httpPost);
                 // Print result
                 System.out.println(response.getStatusLine().getStatusCode());
                 System.out.println(EntityUtils.toString(response.getEntity()));
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
     }
     ```
     "body"由具体文本格式决定，此处以json为例。
     
    
 
