Updated on 2024-04-30 GMT+08:00

Access Authenticated Using an Application

You can enable application authentication when deploying a real-time service. ModelArts registers an API that supports application authentication for the service. After this API is authorized to an application, you can call this API using the AppKey/AppSecret or AppCode of the application.

The process of application authentication for a real-time service is as follows:

  1. Enabling Application Authentication: Enable application authentication. You can select an existing application or create an application.
  2. Managing Authorization of Real-Time Services: Manage the created application, including viewing, resetting, or deleting the application, binding or unbinding real-time services for the application, and obtaining the AppKey/AppSecret or AppCode.
  3. Application Authentication: Authentication is required for calling an API that supports application authentication. Two authentication modes (AppKey+AppSecret or AppCode) are provided. You can select either of them.
  4. Sending an Inference Request

Prerequisites

  • Data has been prepared. Specifically, you have created an AI application in the Normal state in ModelArts.
  • The account is not in arrears to ensure available resources for service running.
  • The local path to the inference file has been obtained. The path can be an absolute path (for example, D:/test.png for Windows and /opt/data/test.png for Linux) or a relative path (for example, ./test.png).

Enabling Application Authentication

When deploying an AI application as a real-time service, you can enable application authentication. You can also modify a deployed real-time service to support application authentication.

  1. Log in to the ModelArts management console and choose Service Deployment > Real-Time Services.
  2. Enable application authentication.
    • When deploying a model as a real-time service, configure the required parameters and enable application authentication on the Deploy page.
    • For a deployed real-time service, go to the Real-Time Services page, and click Modify in the Operation column of the service. On the service modification page that is displayed, enable application authentication.
      Figure 1 Enabling application authentication
  3. Select an application for authorization from the drop-down list. If no application is available, create one as follows:
    • Click Create Application on the right, enter the application name and description, and click OK. By default, the application name starts with app_. You can change the application name.
    • On the Service Deployment > Real-Time Services page, click Authorize. On the Manage Authorization of Real-Time Services page, click Create Application. For details, see Managing Authorization of Real-Time Services.
  4. After enabling application authentication, authorize a service that supports application authentication to the application. Then, you can use the generated AppKey/AppSecret or AppCode to call the service's API that supports application authentication.

Managing Authorization of Real-Time Services

If you want to use application authentication, it is a good practice to create an application on the authorization management page before deploying a real-time service. In the navigation pane, choose Service Deployment > Real-Time Services. On the Real-Time Services page, click Authorize. The Manage Authorization of Real-Time Services dialog box is displayed. From there, you can create and manage applications, including viewing, resetting, and deleting applications, unbinding real-time services from applications, and obtaining the AppKey/AppSecret or AppCode.

Figure 2 Managing authorization for real-time services
  • Creating an application

    Click Create Application, enter the application name and description, and click OK. By default, the application name starts with app_. You can change the application name.

  • Viewing, resetting, or deleting an application

    View, reset, or delete an application by clicking the corresponding icon in the Operation column of the application. After an application is created, the AppKey and AppSecret are automatically generated for application authentication.

  • Unbinding a service

    In front of the target application name, click to view the real-time services bound to the application. Click Unbind in the Operation column to cancel the binding. Then, this API cannot be called.

  • Obtaining the AppKey/AppSecret or AppCode

    Application authentication is required for API calling. The AppKey and AppSecret are automatically generated during application creation. Click in the Operation column of the application in the Manage Authorization of Real-Time Services dialog box to view the complete AppSecret. Click in front of the application name to expand the drop-down list. Click +Add AppCode to automatically generate an AppCode. Then, click in the Operation column to view the complete AppCode.

    Figure 3 Adding the AppCode

Application Authentication

When a real-time service that supports application authentication is in the Running state, the service' API can be called. Before calling the API, perform application authentication.

When application authentication is used and the simplified authentication mode is enabled, you can use the AppKey/AppSecret for signature and verification, or AppCode for simplified authentication of API requests. (Simplified authentication is used by ModelArts by default.) AppKey/AppSecret-based authentication is recommended because it is more secure than AppCode-based authentication.

  • AppKey/AppSecret-based authentication: The AppKey and AppSecret are used to encrypt a request, identify the sender, and prevent the request from being modified. When using AppKey/AppSecret-based authentication, use a dedicated signing SDK to sign requests.
    • AppKey: access key ID of the application, which is a unique identifier used together with a secret access key to sign requests cryptographically.
    • AppSecret: application secret access key, used together with the Access Key ID to encrypt the request, identify the sender, and prevent the request from being tempered.

    AppKeys can be used for simplified authentication. When an API is called, the apikey parameter (value: AppKey) is added to the HTTP request header to accelerate authentication.

  • AppCode-based authentication: Requests are authenticated using AppCodes.

    In AppCode-based authentication, the X-Apig-AppCode parameter (value: AppCode) is added to the HTTP request header when an API is called. The request content does not need to be signed. The API gateway only verifies the AppCode, achieving quick response.

You can obtain the API, AppKey/AppSecret, and AppCode from the Usage Guides tab page on the service details page (see Figure 4) or from the real-time service authorization management page (see Figure 2). Use the API URL in the red box in the following figure. If a path is defined for apis in the model configuration file, the URL must be followed by the user-defined path, for example, {URL of the real-time service}/predictions/poetry.

Figure 4 Obtaining the API address

Method 1: Use Python to Send an Inference request Through AppKey/AppSecret-based Authentication

  1. Download the Python SDK and configure it in the development tool. For details, see Integrating the Python SDK for API request signing.
  2. Create a request body for inference.
    • File input
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      # coding=utf-8
      
      import requests
      from apig_sdk import signer
      
      if __name__ == '__main__':
          # Config url, ak, sk and file path.
          url = "URL of the real-time service"
          app_key = "AppKey"
          app_secret = "AppSecret"
          file_path = "Local path to the inference file"
      
          # Create request, set method, url, headers and body.
          method = 'POST'
          headers = {"x-sdk-content-sha256": "UNSIGNED-PAYLOAD"}
          request = signer.HttpRequest(method, url, headers)
      
          # Create sign, set the AK/SK to sign and authenticate the request.
          sig = signer.Signer()
          sig.Key = app_key
          sig.Secret = app_secret
          sig.Sign(request)
      
          # Send request
          files = {'images': open(file_path, 'rb')}
          resp = requests.request(request.method, request.scheme + "://" + request.host + request.uri, headers=request.headers, files=files)
      
          # Print result
          print(resp.status_code)
          print(resp.text)
      
      Request body format of files: files = {"Request parameter": ("Load path", File content, "File type")}. For details about parameters of files, see Table 1.
      Table 1 Parameters of files

      Parameter

      Mandatory

      Description

      Request parameter

      Yes

      Parameter name of the real-time service.

      Load path

      No

      Path in which the file is stored.

      File content

      Yes

      Content of the file to be uploaded.

      File type

      No

      Type of the file to be uploaded, which can be one of the following options:

      • txt: text/plain
      • jpg/jpeg: image/jpeg
      • png: image/png
    • Text input (JSON)

      The following is an example of the request body for reading the local inference file and performing Base64 encoding:

      # coding=utf-8
      
      import base64
      import json
      import requests
      from apig_sdk import signer
      
      if __name__ == '__main__':
          # Config url, ak, sk and file path.
          url = "URL of the real-time service"
          app_key = "AppKey"
          app_secret = "AppSecret"
          file_path = "Local path to the inference file"
          with open(file_path, "rb") as file:
              base64_data = base64.b64encode(file.read()).decode("utf-8")
      
          # Create request, set method, url, headers and body.
          method = 'POST'
          headers = {
              'Content-Type': 'application/json'
          }
          body = {
              'image': base64_data
          }
          request = signer.HttpRequest(method, url, headers, json.dumps(body))
      
          # Create sign, set the AppKey&AppSecret to sign and authenticate the request.
          sig = signer.Signer()
          sig.Key = app_key
          sig.Secret = app_secret
          sig.Sign(request)
      
          # Send request
          resp = requests.request(request.method, request.scheme + "://" + request.host + request.uri, headers=request.headers, data=request.body)
      
          # Print result
          print(resp.status_code)
          print(resp.text)

      The body name is determined by the input parameter of the real-time service. The parameter name must be the same as that of the input parameter of the string type. image is used as an example. The value of base64_data in body is of the string type.

Method 2: Use Java to Send an Inference request Through AppKey/AppSecret-based Authentication

  1. Download the Java SDK and configure it in the development tool. For details, see Integrating the Java SDK for API request signing.
  2. Create a Java request body for inference.

    In the APIG Java SDK, request.setBody() can only be a string. Therefore, only text inference requests are supported.

    The following is an example of the request body (JSON) for reading the local inference file and performing Base64 encoding:

    // Package name of the demo.
    package com.apig.sdk.demo;
    
    import com.cloud.apigateway.sdk.utils.Client;
    import com.cloud.apigateway.sdk.utils.Request;
    import org.apache.http.HttpHeaders;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.client.methods.HttpRequestBase;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.util.EntityUtils;
    
    public class MyAkSkTest {
    
        public static void main(String[] args) {
            String url = "URL of the real-time service";
            String appKey = "AppKey";
            String appSecret = "AppSecret";
            String body = "{}";
    
            try {
                // Create request
                Request request = new Request();
    
                // Set the AK/AppSecret to sign and authenticate the request.
                request.setKey(appKey);
                request.setSecret(appSecret);
    
                // Specify a request method, such as GET, PUT, POST, DELETE, HEAD, and PATCH.
                request.setMethod(HttpPost.METHOD_NAME);
    
                // Add header parameters
                request.addHeader(HttpHeaders.CONTENT_TYPE, "application/json");
    
                // Set a request URL in the format of https://{Endpoint}/{URI}.
                request.setUrl(url);
    
                // Special characters, such as the double quotation mark ("), contained in the body must be escaped.
                request.setBody(body);
    
                // Sign the request.
                HttpRequestBase signedRequest = Client.sign(request);
    
                // Send request.
                CloseableHttpResponse response = HttpClients.createDefault().execute(signedRequest);
    
                // Print result
                System.out.println(response.getStatusLine().getStatusCode());
                System.out.println(EntityUtils.toString(response.getEntity()));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    body is determined by the text format. JSON is used as an example.

Method 3: Use Python to Send an Inference request Through AppCode-based Authentication

  1. Download the Python SDK and configure it in the development tool. For details, see Integrating the Python SDK for API request signing.
  2. Create a request body for inference.
    • File input
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      # coding=utf-8
      
      import requests
      
      if __name__ == '__main__':
          # Config url, app code and file path.
          url = "URL of the real-time service"
          app_code = "AppCode"
          file_path = "Local path to the inference file"
      
          # Send request.
          headers = {
              'X-Apig-AppCode': app_code
          }
          files = {
              'images': open(file_path, 'rb')
          }
          resp = requests.post(url, headers=headers, files=files)
      
          # Print result
          print(resp.status_code)
          print(resp.text)
      

      The files name is determined by the input parameter of the real-time service. The parameter name must be the same as that of the input parameter of the file type. In this example, images is used.

    • Text input (JSON)

      The following is an example of the request body for reading the local inference file and performing Base64 encoding:

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      # coding=utf-8
      
      import base64
      import requests
      
      if __name__ == '__main__':
          # Config url, app code and request body.
          url = "URL of the real-time service"
          app_code = "AppCode"
          file_path = "Local path to the inference file"
          with open(file_path, "rb") as file:
              base64_data = base64.b64encode(file.read()).decode("utf-8")
      
          # Send request
          headers = {
              'Content-Type': 'application/json',
              'X-Apig-AppCode': app_code
          }
          body = {
              'image': base64_data
          }
          resp = requests.post(url, headers=headers, json=body)
      
          # Print result
          print(resp.status_code)
          print(resp.text)
      

      The body name is determined by the input parameter of the real-time service. The parameter name must be the same as that of the input parameter of the string type. image is used as an example. The value of base64_data in body is of the string type.

Method 4: Use Java to Send an Inference request Through AppCode-based Authentication

  1. Download the Java SDK and configure it in the development tool. For details, see Integrating the Java SDK for API request signing.
  2. (Optional) If the input of the inference request is in the file format, the Java project depends on the httpmime module.
    1. Add httpmime-x.x.x.jar to the libs folder. Figure 5 shows a complete Java dependency library.

      You are advised to use httpmime-x.x.x.jar 4.5 or later. Download httpmime-x.x.x.jar from https://mvnrepository.com/artifact/org.apache.httpcomponents/httpmime.

      Figure 5 Java dependency library
    2. After httpmime-x.x.x.jar is added, add httpmime information to the .classpath file of the Java project as follows:
      <?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. Create a Java request body for inference.
    • File input
      A sample Java request body is as follows:
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      // 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 MyAppCodeFile {
      
          public static void main(String[] args) {
              String url = "URL of the real-time service";
              String appCode = "AppCode";
              String filePath = "Local path to the inference file";
      
              try {
                  // Create post
                  HttpPost httpPost = new HttpPost(url);
      
                  // Add header parameters
                  httpPost.setHeader("X-Apig-AppCode", appCode);
      
                  // 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();
              }
          }
      }
      

      The addBinaryBody name is determined by the input parameter of the real-time service. The parameter name must be the same as that of the input parameter of the file type. In this example, images is used.

    • Text input (JSON)

      The following is an example of the request body for reading the local inference file and performing Base64 encoding:

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      // 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 MyAppCodeTest {
      
          public static void main(String[] args) {
              String url = "URL of the real-time service";
              String appCode = "AppCode";
              String body = "{}";
      
              try {
                  // Create post
                  HttpPost httpPost = new HttpPost(url);
      
                  // Add header parameters
                  httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
                  httpPost.setHeader("X-Apig-AppCode", appCode);
      
                  // 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 is determined by the text format. JSON is used as an example.