You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否在PL/SQL中完成AWS认证以实现APEX内的API调用?

在PL/SQL中实现AWS认证以调用API(适配APEX)

完全可以在PL/SQL中实现AWS认证,AWS API的标准认证方式是Signature Version 4,你可以通过手动构造签名的方式,结合UTL_HTTP完成带认证的API调用,下面是具体实现思路和示例:

核心逻辑:AWS Signature Version 4 签名构造

AWS认证的核心是生成符合规范的签名,步骤如下:

  1. 生成基于UTC时间的时间戳和日期戳,格式必须严格匹配AWS要求
  2. 用AWS密钥(Access Key + Secret Key)分层生成签名密钥
  3. 构造包含请求方法、URI、请求头、请求体哈希等信息的待签名字符串
  4. 用签名密钥对待签名字符串做HMAC-SHA256加密得到最终签名
  5. 将签名信息放入Authorization请求头,发起API调用

PL/SQL实现示例

declare
    v_req               utl_http.req;
    v_res               utl_http.resp;
    v_buffer            varchar2(4000);
    v_body              varchar2(4000) := '{"field":"value"}'; -- 请求JSON体
    v_access_key        varchar2(100) := '你的AWS_ACCESS_KEY';
    v_secret_key        varchar2(100) := '你的AWS_SECRET_KEY';
    v_region            varchar2(50) := 'us-east-1'; -- 目标AWS区域
    v_service           varchar2(50) := 's3'; -- 目标AWS服务(如s3、lambda等)
    v_timestamp         varchar2(50);
    v_date_stamp        varchar2(50);
    v_signature_key     raw(256);
    v_string_to_sign    varchar2(4000);
    v_signature         varchar2(200);
    v_auth_header       varchar2(1000);
begin
    -- 生成UTC时间戳和日期戳,格式严格符合AWS要求
    v_timestamp := to_char(systimestamp at time zone 'UTC', 'YYYYMMDD"T"HH24MISS"Z"');
    v_date_stamp := substr(v_timestamp, 1, 8);

    -- 1. 分层生成签名密钥:AWS4密钥 → 日期 → 区域 → 服务 → aws4_request
    v_signature_key := dbms_crypto.mac(
        src => utl_raw.cast_to_raw('aws4_request'),
        typ => dbms_crypto.hmac_sh256,
        key => dbms_crypto.mac(
            src => utl_raw.cast_to_raw(v_service),
            typ => dbms_crypto.hmac_sh256,
            key => dbms_crypto.mac(
                src => utl_raw.cast_to_raw(v_region),
                typ => dbms_crypto.hmac_sh256,
                key => dbms_crypto.mac(
                    src => utl_raw.cast_to_raw(v_date_stamp),
                    typ => dbms_crypto.hmac_sh256,
                    key => utl_raw.cast_to_raw('AWS4' || v_secret_key)
                )
            )
        )
    );

    -- 2. 构造待签名字符串
    v_string_to_sign := 'POST' || chr(10) || -- 请求方法
                        '/your-api-path' || chr(10) || chr(10) || -- API路径,无参数则留空行
                        'content-type:application/json' || chr(10) || -- 需签名的请求头
                        'host:your-aws-api-endpoint.amazonaws.com' || chr(10) ||
                        'x-amz-date:' || v_timestamp || chr(10) || chr(10) || -- 空行分隔头和签名区域
                        'content-type;host;x-amz-date' || chr(10) || -- 签名覆盖的头列表(顺序要一致)
                        utl_raw.cast_to_varchar2(dbms_crypto.hash(utl_raw.cast_to_raw(v_body), dbms_crypto.sh256)); -- 请求体的SHA256哈希

    -- 3. 生成最终签名
    v_signature := lower(utl_raw.cast_to_varchar2(dbms_crypto.mac(
        src => utl_raw.cast_to_raw(v_string_to_sign),
        typ => dbms_crypto.hmac_sh256,
        key => v_signature_key
    )));

    -- 4. 构造Authorization请求头
    v_auth_header := 'AWS4-HMAC-SHA256 Credential=' || v_access_key || '/' || v_date_stamp || '/' || v_region || '/' || v_service || '/aws4_request, ' ||
                     'SignedHeaders=content-type;host;x-amz-date, ' ||
                     'Signature=' || v_signature;

    -- 初始化并发送请求
    v_req := utl_http.begin_request('https://your-aws-api-endpoint.amazonaws.com/your-api-path', 'POST');
    utl_http.set_header(v_req, 'content-type', 'application/json');
    utl_http.set_header(v_req, 'Content-Length', length(v_body));
    utl_http.set_header(v_req, 'x-amz-date', v_timestamp);
    utl_http.set_header(v_req, 'Authorization', v_auth_header);

    utl_http.write_text(v_req, v_body);

    -- 处理响应
    v_res := utl_http.get_response(v_req);
    begin
        loop
            utl_http.read_line(v_res, v_buffer);
            dbms_output.put_line(v_buffer);
        end loop;
        utl_http.end_response(v_res);
    exception
        when utl_http.end_of_body then
            utl_http.end_response(v_res);
    end;
end;
/

关键注意事项

  • 确保数据库用户拥有DBMS_CRYPTO权限,否则无法生成HMAC哈希和签名
  • 时间戳必须是UTC时间,格式不能出错,否则签名验证会失败
  • 签名覆盖的请求头必须和实际发送的头完全一致,包括顺序
  • 如果是GET请求,请求体哈希部分要用空字符串的SHA256哈希值
  • 若请求包含查询参数,需将排序后的参数键值对加入待签名字符串

内容的提问来源于stack exchange,提问作者SpyOnSteven

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 09:18:45