API绑定签名密钥后,API网关向后端服务发送请求时会携带签名信息。后端服务需要集成SDK对请求中的签名进行校验——解析Authorization头提取signingKey和signedHeaders,用Key查找对应的Secret,按相同算法重新计算签名并与客户端签名比对。华为云这份开发指南提供了Java Spring Boot(Filter实现)、Python Flask(装饰器实现)、C ASP.NET Core(IAuthorizationFilter实现)三种主流后端框架的签名校验完整代码,以及时间戳15分钟有效期、Body可重复读取、正则表达式解析Authorization头的关键技术细节。
签名校验的对称逻辑与核心流程
后端签名校验与客户端签名计算是对称的。API网关向后端服务发送请求时,会在Authorization头中携带签名信息,格式为“SDK-HMAC-SHA256 Access=signature_key1, SignedHeaders=host;x-sdk-date, Signature=e11adf...”。后端服务收到请求后执行以下流程:①从Authorization头中解析signingKey和signedHeaders(使用正则表达式);②通过signingKey在本地存储(secrets Map)中查找对应的signingSecret;③从请求中提取signedHeaders声明的头域值;④校验X-Sdk-Date时间戳与服务器时间差不超过15分钟;⑤按相同算法计算签名并与客户端签名比对;⑥匹配则放行业务处理,否则返回401。
校验过程中需要特别注意:对需要读取Body的场景(POST/PUT请求),需将HttpServletRequest包装为可重复读取的RequestWrapper,因为输入流默认只能读取一次。x-sdk-content-sha256头值为“UNSIGNED-PAYLOAD”时跳过Body验证。
Java Spring Boot——Filter实现签名校验
Java实现基于Spring Boot框架,核心类为ApigatewaySignatureFilter,实现Filter接口。静态代码块中从环境变量加载secrets Map:secrets.put(System.getenv("HUAWEICLOUD_SDK_AK1"), System.getenv("HUAWEICLOUD_SDK_SK1"))。doFilter方法中的关键步骤:使用RequestWrapper包装HttpServletRequest实现Body可重复读取;使用正则表达式Pattern.compile("SDK-HMAC-SHA256\\s+Access=([^,]+),\\s?SignedHeaders=([^,]+),\\s?Signature=(\\w+)")解析Authorization头;从secrets中查找signingSecret,不存在则返回401;创建DefaultRequest对象设置method、endpoint、parameters和headers;通过x-sdk-content-sha256判断是否需要读取Body;使用DateTimeFormatter解析X-Sdk-Date并校验15分钟有效期;调用Signer.verify方法验证签名。验证通过则chain.doFilter(request, response)继续处理,否则返回401。
Python Flask——装饰器实现签名校验
Python实现基于Flask框架,核心为requires_apigateway_signature装饰器。secrets字典从环境变量加载:{os.getenv('HUAWEICLOUD_SDK_AK1'): os.getenv('HUAWEICLOUD_SDK_SK1')}。wrapped函数中的关键步骤:从request.headers中获取Authorization;使用re.compile(r'SDK-HMAC-SHA256\s+Access=([^,]+),\s?SignedHeaders=([^,]+),\s?Signature=(\w+)')解析;通过signingKey查找secret;创建signer.HttpRequest对象,设置method、url(request.path)、query(解析query_string)、headers和body;使用datetime.strptime解析X-Sdk-Date并校验15分钟;调用signer.Verify(r, m.group(3))验证;通过则返回f(args, kwargs),否则返回401。示例中GET、POST、PUT、DELETE四个接口均使用@requires_apigateway_signature()装饰器。
C ASP.NET Core——IAuthorizationFilter实现签名校验
C实现基于ASP.NET Core框架,核心为ApigatewaySignatureFilter,实现IAuthorizationFilter接口。secrets字典使用Environment.GetEnvironmentVariable加载。OnAuthorization方法中的关键步骤:使用Regex("SDK-HMAC-SHA256\\s+Access=([^,]+),\\s?SignedHeaders=([^,]+),\\s?Signature=(\\w+)")解析Authorization头;通过key从Dictionary查找secret;创建HttpRequest对象设置method、host、uri、query和headers;使用request.EnableRewind()启用Body可重复读取;使用MemoryStream读取Body并转为UTF-8字符串;使用DateTime.ParseExact解析X-Sdk-Date并校验15分钟;调用Signer.Verify(sdkRequest, groups[3].Value)验证。验证通过则继续执行Controller中的业务逻辑(GET/POST/PUT/DELETE方法),否则context.Result = new UnauthorizedResult()。
签名校验的安全要点与调试方法
安全要点:AK/SK禁止硬编码,必须通过环境变量或配置管理工具存储;签名密钥应定期轮换(至少每90天);Authorization头格式必须严格符合规范,解析失败直接返回401;时间戳校验是防重放攻击的关键,必须检查与服务器时间差;signedHeaders中声明的所有头域必须存在,否则返回401;对需要读取Body的请求必须使用可重复读取的包装类。
调试方法:Authorization头解析失败时检查格式是否符合“SDK-HMAC-SHA256 Access=xxx, SignedHeaders=xxx, Signature=xxx”;签名不匹配时检查AK/SK是否正确、请求体是否被修改、请求头是否完整;时间戳过期时检查服务器NTP同步状态;可使用JavaScript SDK的demo.html生成标准curl命令测试后端服务。回显“Hello World!”表示校验通过,返回401则需检查签名配置。