如何在UniBasic/UniData中使用AWS Signature Version 4通过REST API上传文件至Amazon S3
UniBasic/UniData 调用AWS S3 REST API(Signature Version 4认证)上传文件示例
以下是直接在UniBasic中构造S3 PUT请求并通过SigV4认证的实现示例,包含核心签名生成逻辑和文件上传主程序:
1. 核心SigV4签名生成函数
这个函数负责生成AWS Signature Version 4所需的Authorization头部,处理日期、规范请求、签名密钥等关键步骤:
FUNCTION GENERATE_S3_SIGV4(ACCESS_KEY, SECRET_KEY, REGION, SERVICE, HTTP_METHOD, URL_PATH, QUERY_PARAMS, HEADERS, PAYLOAD_HASH) * 步骤1: 生成UTC时间戳和日期戳 CALL GET_UTC_TIMESTAMP(TIME_STAMP, DATE_STAMP) * 步骤2: 构造规范请求 CANONICAL_REQUEST = HTTP_METHOD : @AM : @AM CANONICAL_REQUEST := CANONICAL_REQUEST : URL_PATH : @AM CANONICAL_REQUEST := CANONICAL_REQUEST : QUERY_PARAMS : @AM CANONICAL_REQUEST := CANONICAL_REQUEST : HEADERS : @AM : @AM CANONICAL_REQUEST := CANONICAL_REQUEST : PAYLOAD_HASH * 步骤3: 构造待签名字符串 STRING_TO_SIGN = "AWS4-HMAC-SHA256" : @AM STRING_TO_SIGN := STRING_TO_SIGN : TIME_STAMP : @AM STRING_TO_SIGN := STRING_TO_SIGN : DATE_STAMP & "/" & REGION & "/" & SERVICE & "/aws4_request" : @AM STRING_TO_SIGN := STRING_TO_SIGN : SHA256(CANONICAL_REQUEST) * 步骤4: 生成多层HMAC密钥 DATE_KEY = HMAC_SHA256("AWS4" : SECRET_KEY, DATE_STAMP) DATE_REGION_KEY = HMAC_SHA256(DATE_KEY, REGION) DATE_REGION_SERVICE_KEY = HMAC_SHA256(DATE_REGION_KEY, SERVICE) SIGNING_KEY = HMAC_SHA256(DATE_REGION_SERVICE_KEY, "aws4_request") * 步骤5: 计算最终签名并构造Authorization头 SIGNATURE = HEX_ENCODE(HMAC_SHA256(SIGNING_KEY, STRING_TO_SIGN)) SIGNED_HEADERS = "host,x-amz-content-sha256,x-amz-date" ;* 需与请求头中的签名头一致 AUTH_HEADER = "AWS4-HMAC-SHA256 Credential=" : ACCESS_KEY & "/" & DATE_STAMP & "/" & REGION & "/" & SERVICE & "/aws4_request," AUTH_HEADER := AUTH_HEADER & "SignedHeaders=" : SIGNED_HEADERS & "," AUTH_HEADER := AUTH_HEADER & "Signature=" : SIGNATURE RETURN AUTH_HEADER END FUNCTION
2. 辅助工具函数
UniBasic/UniData通常没有内置的加密函数,需要通过系统命令或第三方库实现:
UTC时间戳生成
FUNCTION GET_UTC_TIMESTAMP(TIME_STAMP, DATE_STAMP) * 返回格式: TIME_STAMP=YYYYMMDDTHHMMSSZ, DATE_STAMP=YYYYMMDD UTC_DATE = OCONV(UTC(), "D2YMD") UTC_TIME = OCONV(UTC(), "MTS") DATE_STAMP = UTC_DATE TIME_STAMP = UTC_DATE : "T" : UTC_TIME : "Z" END FUNCTION
SHA256哈希计算(通过OpenSSL)
FUNCTION SHA256(INPUT_STR) TEMP_FILE = "/tmp/ub_sha256.tmp" OPEN LOCAL TEMP_FILE TO TEMP.FD ELSE RETURN "" WRITE INPUT_STR TO TEMP.FD CLOSE TEMP.FD EXECUTE "openssl dgst -sha256 -hex " : TEMP_FILE CAPTURING OUTPUT PARSE OUTPUT WITH " " TO * HASH DELETE FILE TEMP_FILE RETURN HASH END FUNCTION
HMAC-SHA256计算(通过OpenSSL)
FUNCTION HMAC_SHA256(KEY, MSG) TEMP_KEY_FILE = "/tmp/ub_hmac_key.tmp" TEMP_MSG_FILE = "/tmp/ub_hmac_msg.tmp" OPEN LOCAL TEMP_KEY_FILE TO KEY.FD ELSE RETURN "" WRITE KEY TO KEY.FD CLOSE KEY.FD OPEN LOCAL TEMP_MSG_FILE TO MSG.FD ELSE RETURN "" WRITE MSG TO MSG.FD CLOSE MSG.FD EXECUTE "openssl dgst -sha256 -hmac $(cat " : TEMP_KEY_FILE : ") " : TEMP_MSG_FILE CAPTURING OUTPUT PARSE OUTPUT WITH " " TO * HASH DELETE FILE TEMP_KEY_FILE DELETE FILE TEMP_MSG_FILE RETURN HASH END FUNCTION
十六进制编码
FUNCTION HEX_ENCODE(BIN_STR) HEX_STR = "" FOR I=1 TO LEN(BIN_STR) HEX_STR := HEX_STR : OCONV(SEQ(BIN_STR[I,I]), "X") NEXT I RETURN HEX_STR END FUNCTION
3. 文件上传主程序
PROGRAM UPLOAD_TO_S3 * 配置参数 ACCESS_KEY = "YOUR_AWS_ACCESS_KEY" SECRET_KEY = "YOUR_AWS_SECRET_KEY" REGION = "us-east-1" BUCKET_NAME = "your-target-bucket" OBJECT_KEY = "documents/uploaded_file.txt" ;* S3中的对象路径 LOCAL_FILE = "/path/to/your/local/file.txt" ;* UniData本地文件路径 * 读取本地文件内容 OPEN LOCAL LOCAL_FILE TO FILE.FD ELSE PRINT "Error: 无法打开本地文件 " : LOCAL_FILE STOP END READSEQ FILE_CONTENT FROM FILE.FD ELSE FILE_CONTENT = "" CLOSE FILE.FD * 计算文件内容的SHA256哈希 PAYLOAD_HASH = SHA256(FILE_CONTENT) * 构造请求基础信息 HTTP_METHOD = "PUT" URL_PATH = "/" : BUCKET_NAME : "/" : OBJECT_KEY SERVICE = "s3" ENDPOINT = BUCKET_NAME & ".s3." & REGION & ".amazonaws.com" * 生成请求头 CALL GET_UTC_TIMESTAMP(TIME_STAMP, DATE_STAMP) HEADERS = "host:" : ENDPOINT : @AM HEADERS := HEADERS & "x-amz-content-sha256:" : PAYLOAD_HASH : @AM HEADERS := HEADERS & "x-amz-date:" : TIME_STAMP * 获取Authorization头 CALL GENERATE_S3_SIGV4(ACCESS_KEY, SECRET_KEY, REGION, SERVICE, HTTP_METHOD, URL_PATH, "", HEADERS, PAYLOAD_HASH) TO AUTH_HEADER * 构造完整HTTP请求 REQUEST = HTTP_METHOD : " " : URL_PATH : " HTTP/1.1" : @AM REQUEST := REQUEST : HEADERS : @AM REQUEST := REQUEST : "Authorization:" : AUTH_HEADER : @AM : @AM REQUEST := REQUEST : FILE_CONTENT * 发送HTTPS请求(示例使用curl,若UniBasic支持原生HTTPS可替换) EXECUTE "curl -X PUT -d @- -k " : "https://" : ENDPOINT : URL_PATH : " -H 'Authorization: " : AUTH_HEADER : "' -H 'host: " : ENDPOINT : "' -H 'x-amz-content-sha256: " : PAYLOAD_HASH : "' -H 'x-amz-date: " : TIME_STAMP : "'" CAPTURING RESPONSE <@REQUEST PRINT "S3响应: " : RESPONSE END PROGRAM
关键注意事项
- 权限验证:确保AWS Access Key拥有
s3:PutObject权限,且Bucket策略允许该操作。 - HTTPS支持:如果UniBasic原生不支持HTTPS请求,使用
curl是简便的替代方案,也可以通过Socket配合SSL库实现原生请求。 - 时间同步:服务器时间需与UTC时间同步,否则SigV4签名会验证失败。
- 特殊字符处理:如果对象键或文件内容包含特殊字符,需按S3规范进行URL编码或处理。
内容的提问来源于stack exchange,提问作者Marvado
相关产品推荐
相关产品推荐

