接口安全性问题01——接口签名

接口安全性问题 

我们写过很多接口,有没有想想接口的安全性呢?jwt,openid 侧重 于 认证(就是用户是谁),OAuth2 侧重于授权(就是说这个东西是否有权限访问),接口签名呢 侧重于安全

1.请求来源(身份)是否合法?
2.请求参数被篡改?
3.请求的唯一性(不可复制)

 

 

 今天来介绍dotnet环境下接口签名处理

签名介绍:

AccessKey&SecretKey 使用md5签名处理放篡改

请求身份

为开发者分配AccessKey(开发者标识,确保唯一)和SecretKey(用于接口加密,确保不易被穷举,生成算法不易被猜测),也可以自己生成!

防止篡改

参数签名

  1. 按照请求参数名的字母升序排列非空请求参数(包含AccessKey),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA;
  2. 在stringA最后拼接上Secretkey得到字符串stringSignTemp;
  3. 对stringSignTemp进行MD5运算,并将得到的字符串所有字符转换为大写,得到sign值。

请求携带参数AccessKeySign,只有拥有合法的身份AccessKey和正确的签名Sign才能放行。这样就解决了身份验证和参数篡改问题,即使请求参数被劫持,由于获取不到SecretKey(仅作本地加密使用,不参与网络传输),无法伪造合法的请求。

重放攻击

虽然解决了请求参数被篡改的隐患,但是还存在着重复使用请求参数伪造二次请求的隐患。

timestamp+nonce+加密字符串 方案

nonce指唯一的随机字符串,用来标识每个被签名的请求。通过为每个请求提供一个唯一的标识符,服务器能够防止请求被多次使用(记录所有用过的nonce以阻止它们被二次使用)。

然而,对服务器来说永久存储所有接收到的nonce的代价是非常大的。可以使用timestamp来优化nonce的存储

假设允许客户端和服务端最多能存在15分钟的时间差,同时追踪记录在服务端的nonce集合。当有新的请求进入时,首先检查携带的timestamp是否在15分钟内,如超出时间范围,则拒绝,然后查询携带的nonce,如存在已有集合,则拒绝。否则,记录该nonce,并删除集合内时间戳大于15分钟的nonce(可以使用redis的expire,新增nonce的同时设置它的超时失效时间为15分钟)。

实现

  构造secret:

  前端:

1.生成当前时间戳timestamp=now和唯一随机字符串nonce=random
2.封装加密字典 GetSecretParams 包含有加密串1,加密串2

3.计算参数签名 GetSignature 遍历排序后的字典,将所有参数按"key=value"格式拼接在一起, 使用MD5对待签名串求签 生成一个MD5加密后的token
4.拼接 secretstr =
$"timestamp={timestamp}&nonce={nonce}&apptype={"Web"}&signature={token}"; 

5.urlbase64转码处理secretstr得到 secret1 ;

最终请求在请求的header中加上键值对 secret:secret1

  验证secret:

  服务端:

 

 

  

说明:

1.secret1和secret2可以切换成非堆成加密的AccessKey 和 SecretKey,可以多添加一个验证

2.本次验证利用的是md5的不可逆性,验证两次生成的签名是否相同,不相同则说明签名被篡改了。

3.timestamp 参数时间各有不同,具体看项目要求!

项目代码demo地址: https://github.com/Hedgehogcat/2023

 

posted @ 2023-03-05 20:30  失去刺猬的猫  阅读(146)  评论(0编辑  收藏  举报