API接口签名(app接口签名)

createh52个月前 (02-01)技术教程12

前言

基于安全考虑(防止伪造、防止重放),网关提供可配置的针对关键接口进行签名的功能。

一.接口签名设计

由于新规范,我们统一使用POST请求和request json body进行参数传递,所以,不考虑GET请求和query参数的场景。

1.签名规则

签名公式

sign = subString(md5(body + & + secureKey + & + nonce + & + timestamp),8, 24) + | + nonce + | + timestamp

  • 以UTF-8作为编码。
  • body 仅支持 application/json、application/x-www-form-urlencodedtext/plain 这几种content-type类型的body。默认为“”(空字符串)。
  • secureKey 为内置于 App 的安全 key,值类型为 UUID 字符串。由后网关服务分配 ,不同的App版本的secureKey可能不同
    例如:app-version
  • nonce 为随机值,保证每次计算的md5盐均不相同。值为1000-9999的四位随机数。
  • timestamp 校验客户端请求发送时间与服务端时间偏移量是否在和合法范围最终完整的实现,防?伪造请求,防?重放攻击。时间搓统一取零时区的当前时间戳 不能为空
  • 以上参数间(body、secureKey、nonce、timestamp)以&拼接。

2.签名传输

签名最终以上形式,组织成字符串,放到请求头的sign中。


二.header参数签名设计

1.签名规则

headers签名

header-sign = subString(md5(headers + & + secureKey + & + nonce + & + timestamp),8, 24) + | + nonce + | + timestamp

  • 以UTF-8作为编码。
  • headers : 参与签名的请求头参数字符串
  • secureKey: 为内置于App 的安全 key,值类型为 UUID 字符串 ,由后网关服务分配 ,与接口签名共用同一个key。不同的App版本的secureKey可能不同(目前统一用一个key 避免key管理混乱)。
  • nonce: 为随机值,保证每次计算的md5盐均不相同。值为1000-9999的四位随机数(与接口签名保持一致)。
  • timestamp: 校验客户端请求发送时间与服务端时间偏移量是否在和合法范围最终完整的实现,防?伪造请求,防?重放攻击。时间戳统一取零时区的当前时间戳 不能为空
  • 以上参数间(headers、secureKey、nonce、timestamp)以&拼接。
  • 请求头参数签名参数名称 header-sign


2.请求头参数签名顺序

  • 参与签名请求头参数排序 签名请求头参数按ASCII码自然顺序作排序。
  • 签名格式 :请求头参数名称+":"+参数的值 参数用‘|’字符串拼接。
  • 例子: keyName1:keyValue1|keyName1:keyValue1 , app-version:3.2|country-id:2|device-id:oikjslfksj 。
  • 如果指定参与签名的header在请求头里根本不存在,使用 key: 来参与签名, 例子: app-version:3.2|country-id:|device-id:


3.签名传输

  • 签名最终以上形式,组织成字符串,放到请求头的header-sign请求参数中。
  • 协商好的android和ios版本 必须要请求头 header-sign


4.增减参与签名的请求头参数配置

  • 网关支持根据版本号动态配置增减签名参数 根据app版本号分组配置在apollo
  • 签名参数规则android和ios最多维护两个版本
  • 配置签名样例:参考网关配置说明 配置映射的java对象类 ApiAuthConfig
  • 修改类注解 动态更新配置 @ApolloExternalConfig(appId = "al-gateway-capi",namespace ="ApiAuthConfig" ,prefix = "api.auth")
  • 参与签名的请求头参数:app-version country-id device-id deviceUUID device-type


三.签名检验

在后端,提供可针对特定api的配置方式,按以上签名方式组织校验。

1.网关配置说明

网关签名配置说明




备注:

  • 凡是启动签名的android和ios版本必须带请求头参数sign和hender-sign参数
  • 过滤器是capi全局过滤器 代码逻辑需兼容区分非终端路由请求的 不需要参与对应的签名校验
  • 是否开启签名开关
    enableApiAuth 设置为true开启签名,
    signWhiteListUrl 设置灰度签名url
    android-api-secure-key 设置android 签名条件
    ios-api-secure-key 设置ios签名条件
  • 线上环境可以根据以上参数动态调整灰度签名功能

2.功用及各参数作用说明

假设有如下接口:



那么我们可以通过证书篡改或直接穷举,截取到这个接口及其格式(所需请求头和请求参数)。当知道接口格式而没加签名,会存在什么潜在安全问题呢?比如,

1、穷举接口参数偷取数据。

2、截取支付接口信息,修改用户id或金额去支付,或者重放请求信息,重复支付。

因为用户设备所处的环境复杂多样,接口签名可以保证在用户设备https证书被篡改情况下,一些重要接口仍然得到保护。

参数说明

假设单单使用 body + secureKey 的加密方式,可以防止一般情况下的接口参数伪造。

nonce 在前面基础上能够防止攻击者记录下接口参数和签名值的重放攻击。

timestamp 能够一定程度防止攻击者单单是截取了用户的请求,直接进行重放。

关于noncetimestamp的意义说明,请点击查看:API接口防止参数篡改和重放攻击说明


辅助debug功能约定:

事项

测试环境


正式环境


客户端

网关

客户端

网关

判断是否签名

请求头塞入isSign=1

根据isSign=1来判断

无isSign请求头

根据客户端类型和版本号判断

是否塞入签名中间过程信息

通通都有

sign-before-md5:

sign-md5:

如果签名过程发生异常,则增加:

sign-e: 错误信息

仅签名校验失败时,在errorMsg里返回.

测试包,切到正式环境,有

sign-before-md5:

sign-md5:

等信息.

正式包没有这些信息.

只返回常规信息.




Reference

[1] 阿里云 | MTOP、API网关

[2] 微信支付 | 微信支付接口签名

相关文章

Java开发中的加密、解密、签名、验签,密钥,证书,这篇就够了

先说一下两个重要的工具OpenSSL:OpenSSL整个软件包大概可以分成三个主要的功能部分:SSL协议库libssl、应用程序命令工具以及密码算法库libcrypto。它使用标准的文件格式(PEM/...

源码分享:在pdf上加盖电子签章(pdf加盖电子签名)

在pdf上加盖电子签章,并不是只是加个印章图片,。而是要使用一对密钥中的私钥对文件进行签字。为啥要用私钥呢?很简单,因为公钥是公开的,其他人才可以用公钥为你证明,这个文件是你签的。这就是我们常说的:私...

如何确保消息只被消费一次:Java实现详解

引言在分布式系统中,消息传递是系统组件间通信的重要方式,而确保消息在传递过程中只被消费一次是一个关键问题。如果一个消息被多次消费,可能会导致业务逻辑重复执行,进而产生数据不一致、错误操作等问题。特别是...

Java基础——Java多线程(Lock接口详解)

1 基本概括2 主要介绍2.1 Lock接口的作用2.1.1 简单介绍锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源,解决数据的一致性问题。在Lock接口出现...

Java程序员学习Typescript初级篇(java程序猿)

引言对于 Java 程序员来说,TypeScript(简称 TS)是一门非常值得学习的语言。TS 是 JavaScript 的一个超集,它在 JavaScript 的基础上添加了静态类型系统,这与 J...

java代码规范,你了解多少?(一段java代码的详细解说)

一、为啥要有代码规范?1.代码规范可以加快团队间的协作对于每个项目的开发,大多数是由一个团队来完成的,团队内部的人来自四面八方,每个人的代码风格也大不相同,如果没有统一的代码规范,那么代码的可读性会大...