Function Compute は HTTP トリガーの署名認証をサポートしています。トリガーに対して署名認証が有効になっている場合、Function Compute ゲートウェイがリクエストを認証します。関数でリクエスト署名を認証する必要がないため、ビジネスロジックに集中できます。このトピックでは、コンソールで HTTP トリガーの署名認証を構成する方法と、署名を使用してトリガーへのアクセスを検証する方法について説明します。
HTTP トリガーの署名認証を有効にする
このセクションでは、既存の HTTP トリガーの署名認証を有効にする方法について説明します。まず、関数を作成する必要があります。詳細については、「関数を作成する」をご参照ください。
Function Compute コンソールにログインします。左側のナビゲーションウィンドウで、 を選択します。
上部のナビゲーションバーで、リージョンを選択します。[関数] ページで、対象の関数をクリックします。
関数設定ページで、[トリガー] タブを選択します。次に、対象のトリガーの [アクション] 列で、[編集] をクリックします。
[トリガーの編集] パネルで、[認証方法] を [署名認証] に設定します。次に、[OK] をクリックします。
署名を使用して HTTP トリガー URL にアクセスする
HTTP トリガーの署名メソッドは、Alibaba Cloud SDK の署名メカニズムに従います。詳細については、「署名メカニズム」をご参照ください。Alibaba Cloud SDK は、さまざまな言語の署名メソッドを提供します。プロセスは次のとおりです。
Alibaba Cloud SDK を使用して署名文字列を生成します。
HTTP リクエストの Authorization ヘッダーに署名文字列を設定します。
任意の HTTP クライアントを使用してリクエストを送信します。
さまざまな言語の署名 SDK
次のショートカットを使用して、さまざまな言語の Alibaba Cloud 署名 SDK をインストールします。
言語 | SDK |
Go | go get github.com/alibabacloud-go/openapi-util/service |
Python | pip install alibabacloud-openapi-util |
Node.js | npm install @alicloud/openapi-util |
Java | |
さまざまな言語のリクエスト例
次のリクエスト例は参照用です。詳細については、「署名メカニズム」をご参照ください。
# -*- coding: utf-8 -*-
import os
from datetime import datetime
from urllib.parse import urlparse, parse_qs
import requests
from alibabacloud_openapi_util.client import Client as util
from Tea.request import TeaRequest
accessKeyId = os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID']
accessKeySecret = os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET']
securityToken = os.environ.get('ALIBABA_CLOUD_SECURITY_TOKEN', '') # オプション。STS を使用する場合に必要です。
# method パラメーターは、POST や GET などの大文字にする必要があります。GET メソッドを使用する場合は、requests.post を requests.get に変更します。
method = 'POST'
body = 'hello world'
url = 'https://xx.cn-shanghai.fcapp.run/hello?foo=bar' # HTTP トリガー URL
date = datetime.utcnow().isoformat('T')[:19]+'Z'
headers = {
'x-acs-date': date,
'x-acs-security-token': securityToken
}
parsedUrl = urlparse(url)
authRequest = TeaRequest()
authRequest.method = method
authRequest.pathname = parsedUrl.path.replace('$', '%24')
authRequest.headers = headers
authRequest.query = {k: v[0] for k, v in parse_qs(parsedUrl.query).items()}
auth = util.get_authorization(authRequest, 'ACS3-HMAC-SHA256', '', accessKeyId, accessKeySecret)
headers['authorization'] = auth
# GET メソッドを使用する場合は、requests.post を requests.get に変更します。
resp = requests.post(url, body, headers=headers)
print(resp.text)
const util = require("@alicloud/openapi-util");
const axios = require('axios');
async function main() {
const accessKeyId = process.env['ALIBABA_CLOUD_ACCESS_KEY_ID'];
const accessKeySecret = process.env['ALIBABA_CLOUD_ACCESS_KEY_SECRET'];
const securityToken = process.env['ALIBABA_CLOUD_SECURITY_TOKEN'] || ''; // オプション。STS を使用する場合に必要です。
// method パラメーターは、POST や GET などの大文字にする必要があります。GET メソッドを使用する場合は、axios.post を axios.get に変更します。
const method = 'POST';
const body = 'hello world';
const url = 'https://xx.cn-shanghai.fcapp.run/hello?foo=bar' // HTTP トリガー URL
const date = new Date().toISOString();
let headers = {
'x-acs-date': date,
'x-acs-security-token': securityToken
};
const parsedUrl = new URL(url);
const authRequest = {
method: method,
pathname: parsedUrl.pathname.replace('$', '%24'),
headers: headers,
query: Object.fromEntries(parsedUrl.searchParams),
};
console.log('auth: ', authRequest);
const auth = util.default.getAuthorization(authRequest, 'ACS3-HMAC-SHA256', '', accessKeyId, accessKeySecret);
headers['authorization'] = auth;
// GET メソッドを使用する場合は、axios.post を axios.get に変更します。
const resp = await axios.post(url, body, {
headers: headers,
});
console.log('resp: ', resp.data);
}
main().catch(console.error);
package main
import (
"io/ioutil"
"log"
"net/http"
"os"
"strings"
"time"
openapiutil "github.com/alibabacloud-go/openapi-util/service"
"github.com/alibabacloud-go/tea/tea"
)
func main() {
accessKeyId := tea.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
accessKeySecret := tea.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
securityToken := tea.String(os.Getenv("ALIBABA_CLOUD_SECURITY_TOKEN")) // オプション。STS を使用する場合に必要です。
// method パラメーターは、大文字にする必要があります。
method := "POST"
body := "hello world"
url := "https://xx.cn-shanghai.fcapp.run/hello?foo=bar" // HTTP トリガー URL
req, err := http.NewRequest(method, url, strings.NewReader(body))
if err != nil {
log.Printf("new request error: %v", err)
return
}
date := time.Now().UTC().Format(time.RFC3339)
req.Header.Set("x-acs-date", date)
req.Header.Set("x-acs-security-token", *securityToken)
authRequest := &tea.Request{
Method: &method,
Pathname: tea.String(strings.ReplaceAll(req.URL.Path, "$", "%24")),
Headers: make(map[string]*string),
Query: make(map[string]*string),
}
for k := range req.URL.Query() {
authRequest.Query[k] = tea.String(req.URL.Query().Get(k))
}
for k := range req.Header {
authRequest.Headers[k] = tea.String(req.Header.Get(k))
}
auth := openapiutil.GetAuthorization(authRequest, tea.String("ACS3-HMAC-SHA256"), nil, accessKeyId, accessKeySecret)
req.Header.Set("authorization", *auth)
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Printf("post error: %v", err)
return
}
defer resp.Body.Close()
buf, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Printf("read body error: %v", err)
return
}
log.Printf("resp: %v, body: %s", resp, string(buf))
}
package com.aliyun.sample;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import com.aliyun.tea.*;
public class Sample {
public static void main(String[] args_) throws Exception {
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
String securityToken = System.getenv("ALIBABA_CLOUD_SECURITY_TOKEN"); // オプション。STS を使用する場合に必要です。
if (securityToken == null) {
securityToken = "";
}
// method パラメーターは、POST や GET などの大文字にする必要があります。GET メソッドを使用する場合は、HttpPost を HttpGet に変更します。
String method = "POST";
String body = "hello world";
String url = "https://xx.cn-shanghai.fcapp.run/hello?foo=bar"; // HTTP トリガー URL
Map<String, String> headers = new HashMap<String, String>();
String date = Instant.now().toString();
headers.put("x-acs-date", date);
headers.put("x-acs-security-token", securityToken);
URI uri = new URI(url);
Map<String, String> query = new HashMap<String, String>();
for (NameValuePair pair : URLEncodedUtils.parse(uri, StandardCharsets.UTF_8)) {
query.put(pair.getName(), pair.getValue());
}
TeaRequest req = new TeaRequest();
req.method = method;
req.pathname = uri.getPath().replace("$", "%24");
req.headers = headers;
req.query = query;
String auth = com.aliyun.openapiutil.Client.getAuthorization(
req, "ACS3-HMAC-SHA256", "", accessKeyId, accessKeySecret);
headers.put("authorization", auth);
// GET メソッドを使用する場合は、HttpPost を HttpGet に変更します。
HttpPost request = new HttpPost(url);
for (Map.Entry<String, String> entry : headers.entrySet()) {
request.setHeader(entry.getKey(), entry.getValue());
}
StringEntity entity = new StringEntity(body);
request.setEntity(entity);
// リクエストを実行する
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
org.apache.http.HttpResponse response = httpClient.execute(request);
String responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
System.out.println(responseString);
}
}
}
手順
このトピックでは、Go を例として、署名を使用して HTTP トリガーにアクセスする方法を示します。
go get github.com/alibabacloud-go/openapi-util/serviceを実行して SDK をインストールします。ローカルマシンで
main.goコードファイルを準備します。このトピックで提供されているサンプルコードを使用できます。詳細については、「さまざまな言語のリクエスト例」をご参照ください。
go run main.goを実行してコードを実行します。コードが正常に実行されると、次の結果が返されます。これは、関数の応答が正しく取得されたことを示します。
2024/02/22 17:21:31 resp: &{200 OK 200 HTTP/1.1 1 1 map[Access-Control-Expose-Headers:[Date,x-fc-request-id] Content-Disposition:[attachment] Content-Length:[14] Content-Type:[text/plain; charset=utf-8] Date:[Thu, 22 Feb 2024 09:21:31 GMT] X-Fc-Request-Id:[1-65d71219-15d63510-fecf237c590c]] 0xc000120040 14 [] false false map[] 0xc000100100 0xc0000e0370}, body: Hello, Golang!
よくある質問
署名認証が有効になっている HTTP トリガーを介して関数にアクセスすると、「required HTTP header Date was not specified」というエラーが表示されるのはなぜですか。
このエラーは、認証が失敗したことを示します。考えられる原因は次のとおりです。
リクエストに署名がありません。
リクエストには署名がありますが、Date ヘッダーが提供されていません。
署名認証が有効になっている HTTP トリガーを介して関数にアクセスすると、「the difference between the request time 'Thu, 04 Jan 2024 01:33:13 GMT' and the current time 'Thu, 04 Jan 2024 08:34:58 GMT' is too large」というエラーが表示されるのはなぜですか。
このエラーは、署名の有効期限が切れていることを示します。現在の時刻を使用してリクエストに再度署名してください。
署名認証が有効になっている HTTP トリガーを介して関数にアクセスすると、「The request signature we calculated does not match the signature you provided. Check your access key and signing method」というエラーが表示されるのはなぜですか。
このエラーは、リクエストの署名が Function Compute によって計算された署名と一致しないために発生し、認証が失敗します。