Alibaba Cloud Dedicated Host (DDH) は、リクエスト署名を使用してAPI呼び出し元を識別します。 これにより、API操作を呼び出すときのデータセキュリティが確保されます。 HTTPまたはHTTPS APIリクエストを開始するときは、リクエストに署名情報を含める必要があります。 このトピックでは、リクエストに署名する方法について説明します。

ステップ1: 正規化されたクエリ文字列を作成する

  1. リクエストパラメーターを並べ替えます。 リクエストパラメーターをアルファベット順に並べて、正規化されたクエリ文字列を作成します。 これらのリクエストパラメーターには、Signatureを除くすべての共通パラメーターと操作固有パラメーターが含まれます。 詳細については、「共通リクエストパラメーター」をご参照ください。
    GETメソッドを使用してリクエストが送信された場合、リクエストパラメーターは疑問符 (?) の後に指定され、URLでアンパサンド (&) で区切られます。
  2. パラメーターをエンコードします。 UTF-8文字セットを使用し、RFC 3986の仕様に従って、リクエストパラメーターとパラメーター値をエンコードします。 次のエンコードルールが使用されます。
    • 文字、数字、ハイフン (-) 、アンダースコア (_) 、ピリオド (.) 、およびチルダ (~) はエンコードする必要はありません。
    • その他の文字は、% XY形式でパーセントエンコードする必要があります。 XYは文字のASCIIコードを16進法で表します。 たとえば、二重引用符 (") は % 22としてエンコードされます。
    • 拡張UTF-8文字は、% XY % ZA... 形式でエンコードされます。
    • スペースは % 20としてエンコードする必要があります。 スペースをプラス記号 (+) としてエンコードしないでください。

      このエンコード形式は、MIMEエンコード形式application/x-www-form-urlencodedとは若干異なります。

      Java標準ライブラリJava.net.URLEncoderを使用している場合は、PercentEncodeを使用してリクエストパラメーターをエンコードできます。 次に、プラス記号 (+) を % 20に、アスタリスク (*) を % 2Aに、% 7Eをチルダ (~) に置き換えて、エンコードされた文字列を取得します。

      プライベート静的最終文字列ENCODING = "UTF-8";
      プライベート静的文字列percentEncode (文字列値) がUnsupportedEncodingException {
      戻り値! =null? URLEncoder.encode(value, ENCODING).replace("+", "% 20").replace("*", "% 2A").replace("% 7E", "~") : null;
      }
  3. 等号 (=) を使用して、リクエストパラメーターとその値を区切ります。
  4. さまざまなリクエストパラメーターを連結するには、アンパサンド (&) を使用します。 パラメーターの順序は、ステップ1で使用した順序と同じでなければなりません。

リクエストの構文 に続く正規化されたクエリ文字列 (CanonicalizedQueryString) を取得できます。

ステップ2: 署名文字列を作成する

  1. 文字列に署名するStringToSignを作成します。 percentEncodeを使用して、手順1で作成した正規化クエリ文字列を処理できます。 次のルールが使用されます。
    StringToSign=
      HTTPMethod + "&" + // HTTPMethod: GETなど、リクエストを行うために使用されるHTTPメソッド。
      percentEncode("/") + "&" + // percentEncode("/"): スラッシュ (/) をUTF-8で % 2Fとしてエンコードします。
      percentEncode(CanonicalizedQueryString) // 手順1で作成した正規化クエリ文字列をエンコードします。
  2. RFC 2104の仕様に基づいて、string-to-sign StringToSignのHMAC-SHA1値を計算します。 この例では、Java Base64エンコード方式が使用されます。
    Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) )
    署名を計算するとき、RFC 2104で指定されたキーは、ASCII値が38のアンパサンド (&) を持つAccessKeySecretです。 詳細については、「AccessKey の作成」をご参照ください。
  3. RFC 3986の仕様に基づいてSignatureパラメーターをエンコードし、エンコードされた署名を正規化されたクエリ文字列に追加します。

例1: パラメータの連結

この例では、パラメータを連結することによって署名を構築する方法を示すために、DescribeDedicatedHosts操作が呼び出される。 AccessKeyIDがtestidに、AccessKeySecretがtestsecretに設定されている場合、次の署名プロセスに進むことができます。
  1. 正規化されたクエリ文字列を作成します。
    http://ecs.aliyuncs.com/?Timestamp=2016-02-23T12%3A46%3A24Z&Format=XML&AccessKeyId=testid&Action=DescribeDedicatedHosts&SignatureMethod=HMAC-SHA1&SignatureNonce=3ee8c1b8-xxxx-xxxx-xxxx-xxxxxxxxxx&Version=2014-05-26&SignatureVersion=1.0
  2. StringToSignを作成します。
    GET&% 2F&AccessKeyId % 3Dtestid % 26アクション % 3DDescribeDedicatedHosts % 26Format % 3DXML % 26SignatureMethod % 3DHMAC-SHA1% 26SignatureNonce % 3D3ee8c1b8-xxxx-xxxx-xxxx-xxxxxxxxx % 26SignatureVersion % 3D1.0% 26タイムスタンプ % 3D2016-2-23T12% 253A24Z 26
  3. 署名値を計算します。 AccessKeySecretがtestsecretに設定されている場合、計算に使用されるキーはtestsecret& です。 計算されたシグネチャはOLeaidS1JvxuMvnyHOwuJ % 2BuX5qY % 3Dです。 この例では、JavaBase64エンコード方式が使用されます。
    Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) )
  4. RFC 3986に基づいてエンコードされたSignature=OLeaidS1JvxuMvnyHOwuJ % 2BuX5qY % 3D文字列を、手順1のURLに追加します。
    http://ecs.aliyuncs.com/?SignatureVersion=1.0&Action=DescribeDedicatedHosts&Format=XML&SignatureNonce=3ee8c1b8-xxxx-xxxx-xxxx-xxxxxxxxx&Version=2014-05-26&AccessKeyId=testid&Signature=OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D&SignatureMethod=HMAC-SHA1&Timestamp=2016-02-23T12%253A46%253A24Z

手順4で新しいURLを取得した後、ブラウザー、cURL、またはwgetを使用してHTTPリクエストを開始し、DescribeDedicatedHosts操作を呼び出して1つ以上の専用ホストの詳細を照会できます。

例2: プログラミング言語の標準ライブラリを使用する

この例では、標準ライブラリを使用して署名を作成する方法を示すためにDescribeDedicatedHosts操作が呼び出されます。 この例では、AccessKeyIDがtestidに設定され、AccessKeySecretがtestsecretに設定され、すべてのリクエストパラメーターがJava Map<String, String> オブジェクトに配置されると仮定します。

  1. エンコード方法を事前定義します。
    プライベート静的最終文字列ENCODING = "UTF-8";
    プライベート静的文字列percentEncode (文字列値) がUnsupportedEncodingException {
      戻り値! =null? URLEncoder.encode(value, ENCODING).replace("+", "% 20").replace("*", "% 2A").replace("% 7E", "~") : null;
    }
  2. Timestampパラメーターの時間形式を事前定義します。 TimestampパラメーターはISO8601仕様に準拠し、UTC + 0である必要があります。
    プライベート静的最終文字列ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
    プライベート静的文字列formatIso8601Date (日付) {
      SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT);
      df.setTimeZone(new SimpleTimeZone(0, "GMT"));
      df.format (日付) を返します。}
  3. 正規化されたクエリ文字列を作成します。
    最終文字列HTTP_METHOD = "GET";
    マップパラメータ=新しいHashMap();
    // リクエストパラメーターを指定します。
    parameters.put("Action", "DescribeDedicatedHosts");
    parameters.put("バージョン" 、"2014-05-26");
    parameters.put("AccessKeyId" 、"testid");
    parameters.put("Timestamp", formatIso8601Date(new Date()));
    parameters.put("SignatureMethod" 、"HMAC-SHA1");
    parameters.put("SignatureVersion" 、"1.0");
    parameters.put("SignatureNonce", UUID.randomUUID().toString());
    parameters.put("フォーマット" 、"XML");
    // リクエストパラメーターを並べ替えます。
    String[] sortedKeys = parameters.keySet().toArray(new String[]{});
    Arrays.sort(sortedKeys);
    final String SEPARATOR = "&";
    // stringToSign文字列を作成します。
    StringBuilder stringToSign = new StringBuilder();
    stringToSign.append(HTTP_METHOD).append(SEPARATOR);
    stringToSign.append(percentEncode("/")).append(SEPARATOR);
    StringBuilder canonicalizedQueryString = new StringBuilder();
    for(String key : sortedKeys) {
    // キーと値をエンコードします。
      canonicalizedQueryString.append("&")
      .append(percentEncode(key)).append("=")
      . append(percentEncode(parameters.get(key)));
    }
    // 正規化されたクエリ文字列をエンコードします。
    stringToSign.append(percentEncode(
      canonicalizedQueryString.toString().substring(1)));
  4. 署名を計算します。 AccessKeySecretがtestsecretに設定されている場合、計算に使用されるキーはtestsecret& です。 計算されたシグネチャはOLeaidS1JvxuMvnyHOwuJ % 2BuX5qY % 3Dです。
    // 次のサンプルコードは、署名の計算方法を示しています。最終文字列ALGORITHM = "HmacSHA1";
    final String ENCODING = "UTF-8";
    key = "testsecret&";
    Mac mac = Mac.getInstance(ALGORITHM);
    mac.init (新しいSecretKeySpec(key.getBytes(ENCODING) 、ALGORITHM));
    byte[] signData = mac.doFinal(stringToSign.getBytes(ENCODING));
    String signature = new String(Base64.encodeBase64(signData));
    RFC 3986の仕様に基づいてSignatureパラメーターをエンコードします。 URLにSignatureパラメーターを追加します。 その後、次の新しいURLを取得できます。
    http://ecs.aliyuncs.com/?SignatureVersion=1.0&Action=DescribeDedicatedHosts&Format=XML&SignatureNonce=3ee8c1b8-xxxx-xxxx-xxxxx-xxxxx&Version=2014-05-26&AccessKeyId=testid&Signature=OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D&SignatureMethod=HMAC-SHA1&Timestamp=2016-02-23T12%253A46%253A24Z
  5. ブラウザー、cURL、またはwgetを使用してHTTPリクエストを送信します。
    既定では、応答は次のXML形式です。formatをJSONに設定すると、応答はJSON形式になります。 詳細については、「レスポンス」をご参照ください。
    <DescribeDedicatedHostsResponse>
      <PageNumber>1</PageNumber>
      <DedicatedHosts>
        <DedicatedHost>
          <DedicatedHostId>dh-2xxxxxxxxxxxxx</DedicatedHostId>
          <ChargeType>PostPaid</ChargeType>
          <Description/>
          <ResourceGroupId />
          <SupportedInstanceTypeFamilies>
            <SupportedInstanceTypeFamily>ecs.se1ne</SupportedInstanceTypeFamily>
          </SupportedInstanceTypeFamilies>
          <インスタンス />
          <コア> 32</calCores>
          <ZoneId>cn-beijing-c</ZoneId>
          <CreationTime>2018-08-13T07:59Z</CreationTime>
          <ソケット> 2</ソケット>
          <Status>Available</Status>
          <DedicatedHostType>ddh.se1ne</DedicatedHostType>
          <RegionId>cn-beijing</RegionId>
          <DedicatedHostName>myDDH</DedicatedHostName>
          <SaleCycle/>
          <AutoReleaseTime />
          <容量>
            <AvailableVcpus>56</AvailableVcpus>
            <TotalMemory>448.0</TotalMemory>
            <TotalVcpus>56</TotalVcpus>
            <AvailableLocalStorage>0</AvailableLocalStorage>
            <TotalLocalStorage>0</TotalLocalStorage>
            <LocalStorageCategory/>
            <AvailableMemory>448.0</AvailableMemory>
          </容量>
          <OperationLocks />
          <MachineId>d7xxxxxxxxxxxxxxxxxdb</MachineId>
          <ExpiredTime>2999-09-08T16:00Z</ExpiredTime>
        </DedicatedHost>
        <DedicatedHost>
          <DedicatedHostId>dh-2xxxxxxxxxxxxx</DedicatedHostId>
          <ChargeType>PostPaid</ChargeType>
          <Description/>
          <ResourceGroupId />
          <SupportedInstanceTypeFamilies>
            <SupportedInstanceTypeFamily>ecs.se1ne</SupportedInstanceTypeFamily>
          </SupportedInstanceTypeFamilies>
          <インスタンス />
          <コア> 32</コア>
          <ZoneId>cn-beijing-c</ZoneId>
          <CreationTime>2018-08-13T07:59Z</CreationTime>
          <ソケット> 2</ソケット>
          <Status>Available</Status>
          <DedicatedHostType>ddh.se1ne</DedicatedHostType>
          <RegionId>cn-beijing</RegionId>
          <DedicatedHostName>myDDH</DedicatedHostName>
          <SaleCycle/>
          <AutoReleaseTime />
          <容量>
            <AvailableVcpus>56</AvailableVcpus>
            <TotalMemory>448.0</TotalMemory>
            <TotalVcpus>56</TotalVcpus>
            <AvailableLocalStorage>0</AvailableLocalStorage>
            <TotalLocalStorage>0</TotalLocalStorage>
            <LocalStorageCategory/>
            <AvailableMemory>448.0</AvailableMemory>
          </容量>
          <OperationLocks />
          <MachineId>fxxxxxxxxxxxxxxx6ca6</MachineId>
          <ExpiredTime>2999-09-08T16:00Z</ExpiredTime>
        </DedicatedHost>
      </DedicatedHosts>
      <TotalCount>2</TotalCount>
      <PageSize>10</PageSize>
      <RequestId>C9E9EA51-6B74-409E-BA40-107126A200D4</RequestId>
    </DescribeDedicatedHostsResponse>