尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

深入原理:erlcloud 如何实现 AWS SigV4 请求签名(附代码解析)

深入原理:erlcloud 如何实现 AWS SigV4 请求签名(附代码解析) 深入原理erlcloud 如何实现 AWS SigV4 请求签名附代码解析【免费下载链接】erlcloudAWS APIs library for Erlang (Amazon EC2, S3, SQS, DDB, ELB and etc)项目地址: https://gitcode.com/gh_mirrors/er/erlcloud你是否好奇过用 Erlang 写的 erlcloud 库在调用 AWS 服务时是如何通过 AWS SigV4 请求签名机制完成身份验证的作为 Erlang 生态中最成熟的 AWS 客户端库erlcloud 覆盖了 EC2、S3、SQS、DynamoDB、ELB 等数十个 AWS 服务而这一切安全通信的基础正是 AWS Signature Version 4简称 SigV4签名算法。本文将从零开始拆解 SigV4 的四步签名流程并结合 erlcloud 的真实源码逐行解析实现细节帮助你彻底理解这套加签-验签机制背后的原理。为什么每个 AWS 请求都需要 SigV4 签名AWS 对外提供的所有 API 都要求携带签名目的有三个验证身份确认请求来自持有 Access Key 的合法用户、防止篡改任何请求内容的改动都会导致签名校验失败、防止重放攻击签名中绑定时间戳与有效期。SigV4 的核心思想是客户端用密钥派生出的签名密钥Signing Key对规范化后的请求做 HMAC-SHA256 计算最终生成一个Authorization请求头发送给 AWS。服务端用同样的规则独立计算一遍两边结果一致才算通过。SigV4 签名的四步核心流程整个签名过程可以浓缩为四步erdcloud 的实现也严格遵循这个顺序构造规范化请求Canonical Request构造待签名字符串String to Sign推导签名密钥Signing Key生成 Authorization 请求头第一步构造规范化请求Canonical Request规范化请求是签名的原材料它把请求的方法、路径、查询参数、请求头整理成一种标准格式确保客户端和服务端看到的是完全一致的字符串。在 erlcloud 中这一步由 canonical_request/5 完成代码如下canonical_request(Method, CanonicalURI, QParams, Headers, PayloadHash) - {CanonicalHeaders, SignedHeaders} canonical_headers(Headers), CanonicalQueryString canonical_query_string(QParams), {[string:to_upper(atom_to_list(Method)), $\n, CanonicalURI, $\n, CanonicalQueryString, $\n, CanonicalHeaders, $\n, SignedHeaders, $\n, PayloadHash], SignedHeaders}.规范化请求由6 个换行分隔的字段组成顺序固定HTTP 方法大写如POST规范化 URI即路径如/规范化查询字符串规范化请求头每行name:value格式已签名请求头列表分号分隔请求体哈希SHA256 的十六进制结果其中规范化请求头的处理值得注意canonical_headers/1 做了三件事把所有头名转小写、去除头值首尾空格、按头名排序最终得到host:...\n...的规整文本同时用分号拼出SignedHeaders列表。而规范化查询字符串则由 canonical_query_string/1 负责先对每个参数做 URL 编码再整体排序最后用连接。编码规则在 erlcloud_http.erl 的url_encode/1中实现——保留A-Z a-z 0-9 - _ . ~这些安全字符其余字符转成%XX形式这与 SigV4 规范完全一致。第二步构造待签名字符串String to Sign拿到规范化请求后还要再包一层壳形成待签名字符串。它的格式是AWS4-HMAC-SHA256 时间戳 凭证范围 规范化请求的SHA256哈希erlcloud 的实现位于 to_sign/3to_sign(Date, CredentialScope, Request) - [AWS4-HMAC-SHA256\n, Date, $\n, CredentialScope, $\n, hash_encode(Request)].其中时间戳Date由 iso_8601_basic_time/0 生成格式为YYYYMMDDTHHMMSSZUTC 时间不带毫秒。凭证范围CredentialScope则由 credential_scope/3 拼出YYYYMMDD/region/service/aws4_request的形式。一个容易被忽略的细节时间戳会作为x-amz-date请求头随请求一起发送AWS 用它来判断签名是否在有效期内默认 15 分钟这就是 SigV4 防重放攻击的关键。第三步推导签名密钥Signing Key签名密钥不是直接用 Secret Access Key而是经过四层 HMAC 链式推导得到的。这样做的好处是即使泄露了某次请求的签名密钥也无法反推出真正的 Secret Key也无法用于其他日期或服务。erlcloud 的实现位于 signing_key/4signing_key(Config, Date, Region, Service) - DateOnly string:left(Date, 8), KDate erlcloud_util:sha256_mac( AWS4 Config#aws_config.secret_access_key, DateOnly), KRegion erlcloud_util:sha256_mac( KDate, Region), KService erlcloud_util:sha256_mac( KRegion, Service), erlcloud_util:sha256_mac( KService, aws4_request).推导链条非常清晰KDate HMAC(AWS4 SecretKey, YYYYMMDD)KRegion HMAC(KDate, region)KService HMAC(KRegion, service)SigningKey HMAC(KService, aws4_request)底层的 HMAC-SHA256 运算封装在 erlcloud_util.erl 中调用的是 Erlang/OTP 的crypto模块。源码中还有一个 TODO 注释签名密钥其实可以按天缓存因为同一台机器同一天内所有请求的 Signing Key 都是相同的缓存能显著减少重复计算——这是性能优化值得关注的点。第四步生成 Authorization 请求头万事俱备最后把签名和凭证信息拼成Authorization请求头。erlcloud 的 sign_v4/8 是整条流程的总指挥sign_v4(Method, Uri, Config, Headers, Payload, Region, Service, QueryParams) - Date iso_8601_basic_time(), {PayloadHash, Headers1} sign_v4_content_sha256_header( [{x-amz-date, Date} | Headers], Payload ), Headers2 case Config#aws_config.security_token of undefined - Headers1; Token - [{x-amz-security-token, Token} | Headers1] end, {Request, SignedHeaders} canonical_request(Method, Uri, QueryParams, Headers2, PayloadHash), CredentialScope credential_scope(Date, Region, Service), ToSign to_sign(Date, CredentialScope, Request), SigningKey signing_key(Config, Date, Region, Service), Signature base16(erlcloud_util:sha256_mac( SigningKey, ToSign)), Authorization authorization(Config, CredentialScope, SignedHeaders, Signature), [{Authorization, lists:flatten(Authorization)} | Headers2].它在进入四步流程前还默默做了三件辅助工作自动添加x-amz-date请求头UTC 当前时间通过 sign_v4_content_sha256_header/2 计算请求体哈希写入x-amz-content-sha256请求头若调用方已显式提供则直接复用如果配置了临时凭证STS Token自动附加x-amz-security-token请求头最终由 authorization/4 拼出标准格式的 Authorization 头AWS4-HMAC-SHA256 CredentialAKID.../20260819/us-east-1/s3/aws4_request, SignedHeadershost;x-amz-content-sha256;x-amz-date, Signature64位十六进制签名erlcloud 中 SigV4 的两种调用方式在 erlcloud 内部SigV4 签名有两个入口分别服务于新老两代 API 风格sign_v4/8完整版签名函数支持自定义 HTTP 方法、路径和查询参数主要服务于 JSON 类 API如 Athena、Lambda、DynamoDB、Kinesis 等例如 erlcloud_athena.erl 中的调用。sign_v4_headers/5sign_v4/8的便捷封装固定使用POST /见 erlcloud_aws.erl适合大批量表单类请求。如果你仔细观察各服务模块会发现 S3、DynamoDB、Lambda 这些热门服务的请求函数最终都会汇聚到sign_v4系列函数上这就是一处实现、全库复用的典型设计。总结一次签名请求的完整生命周期回顾整个流程一次带 SigV4 签名的 AWS 请求在 erlcloud 内部是这样走完的服务模块如 erlcloud_s3.erl组装请求参数调用aws_request_*系列函数erlcloud_aws.erl 中补全content-type等基础头sign_v4/8生成时间戳、计算负载哈希、推导签名密钥、拼接 Authorization 头请求经 erlcloud_retry.erl 带重试策略发出对 409/5xx/429 等状态自动重试AWS 服务端用相同规则验签通过后返回响应理解 SigV4 的原理不仅能帮你排查SignatureDoesNotMatch这类经典报错通常是时钟漂移或 SecretKey 错误还能在自定义服务接入或调试请求时游刃有余。希望这篇解析能成为你掌握 AWS 签名机制的一块跳板。【免费下载链接】erlcloudAWS APIs library for Erlang (Amazon EC2, S3, SQS, DDB, ELB and etc)项目地址: https://gitcode.com/gh_mirrors/er/erlcloud创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表