能否在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认证的核心是生成符合规范的签名,步骤如下:
- 生成基于UTC时间的时间戳和日期戳,格式必须严格匹配AWS要求
- 用AWS密钥(Access Key + Secret Key)分层生成签名密钥
- 构造包含请求方法、URI、请求头、请求体哈希等信息的待签名字符串
- 用签名密钥对待签名字符串做HMAC-SHA256加密得到最终签名
- 将签名信息放入
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
相关产品推荐
相关产品推荐

