如何实现 API 接口签名鉴权?

泥瓦匠BYSocket

共 2427字,需浏览 5分钟

 · 2021-09-28

不点蓝字关注,我们哪来故事?




正文如下

来源:老顾聊技术

  • 前言
  • 签名流程
  • 签名规则
  • 签名的生成
  • 请求头部分
  • 请求URL地址
  • 请求Request参数
  • 请求Body
  • 签名算法实现
  • 总结

前言

前后端分离的开发方式,我们以接口为标准来进行推动,定义好接口,各自开发自己的功能,最后进行联调整合。无论是开发原生的APP还是webapp还是PC端的软件,只要是前后端分离的模式,就避免不了调用后端提供的接口来进行业务交互。

网页或者app,只要抓下包就可以清楚的知道这个请求获取到的数据,也可以伪造请求去获取或攻击服务器;也对爬虫工程师来说是一种福音,要抓你的数据简直轻而易举。那我们怎么去解决这些问题呢?

接口签名

我们先考虑一下接口数据被伪造,以及接口被重复调用的问题,要解决这个问题我们就要用到接口签名的方案,

签名流程

图片

签名规则

  • 1、线下分配appid和appsecret,针对不同的调用方分配不同的appid和appsecret
  • 2、加入timestamp(时间戳),5分钟内数据有效
  • 3、加入临时流水号 nonce(防止重复提交),至少为10位。针对查询接口,流水号只用于日志落地,便于后期日志核查。针对办理类接口需校验流水号在有效期内的唯一性,以避免重复请求。
  • 4、加入签名字段signature,所有数据的签名信息。

以上字段放在请求头中。

签名的生成

签名signature字段生成规则

所有动态参数 = 请求头部分 + 请求URL地址 + 请求Request参数 + 请求Body

上面的动态参数以key-value的格式存储,并以key值正序排序,进行拼接

最后拼接的字符串 在拼接appSecret

signature = DigestUtils.md5DigestAsHex(sortParamsMap + appSecret)

即拼接成一个字符串,然后做md5不可逆加密

请求头部分

请求头=“appId=xxxx&nonce=xxxx×tamp=xxxx&sign=xxx”

请求头中的4个参数是必须要传的,否则直接报异常

请求URL地址

请求URL地址

https://mso.xxxx.com.cn/api/user

请求Request参数

即请求为Get方式的时候,获取的传入的参数

请求Body

即请求为Post时,请求体Body

从request inputstream中获取保存为String形式

签名算法实现

基本原理其实也比较简单,就是自定义filter,对每个请求进行处理;整体流程如下

  • 1)验证必须的头部参数
  • 2)获取头部参数,request参数,Url请求路径,请求体Body,把这些值放入SortMap中进行排序
  • 3)对SortMap里面的值进行拼接
  • 4)对拼接的值进行加密,生成sign
  • 5)把生成的sign和前端传入的sign进行比较,如果不相同就返回错误


👆点击关注,可添加我微信👆

我是 Socket,坚持分享编程,算法,Java 等干货教程


我们来看一下代码

@Component
public class SignAuthFilter extends OncePerRequestFilter{
  static final String FAVICON = "/favicon.ico";
  static final String PREFIX = "attack:signature:";
}
图片

以上是filter类,其中有个appSecret需要自己业务去获取,它的作用主要是区分不同客户端app。并且利用获取到的appSecret参与到sign签名,保证了客户端的请求签名是由我们后台控制的,我们可以为不同的客户端颁发不同的appSecret。

我们再来看看验证头部参数

图片

上图其实就是验证是否传入值;不过其实有个很重要的一点,就是对此请求进行时间验证,如果大于10分钟表示此链接已经超时,防止别人来到这个链接去请求。这个就是防止盗链。

我们在来看看,如何获取各个参数

图片

上面的流程中,会有个额外的安全处理,

  • 防止盗链,我们可以让链接有失效时间
  • 利用nonce参数,防止重复提交

在签名验证成功后,判断是否重复提交,原理就是结合redis,判断是否已经提交过

图片

总结

今天我们用签名的方式,对我们对外提供的接口起到了保护作用;但这种保护仅仅做到了防止别人篡改请求,或者模拟请求。

但是还是缺少对数据自身的安全保护,即请求的参数和返回的数据都是有可能被别人拦截获取的,而这些数据又是明文的,所以只要被拦截,就能获得相应的业务数据。


往期推荐

程序员被公司辞退都12天了,前领导要求回公司讲清楚代码

被迫降级降薪,说好的共同富裕呢?

以为工作了十年,其实却只有一年的工作经验,只不过又重复用了九年

Visual Studio 上架微软商店了,你怎么看?

为什么要使用微服务架构和这些组件?

SpringBoot+Redis 如何防止瞬间几千次的重复提交?


-END-

↑ 点击上方关注我公号  


我是 Socket,坚持分享编程,算法,Java 等干货教程


一枚医科大本科生,开源小作者,半吊子创业爱好者...

半吊子的自己在试错,不知道以后会干什么,但享受现在的试错,试错给我惊讶的生活


喜欢公号的互动分享,感谢关注,路上遇见了你,同一小段时间之路,相伴 ~



长按识别,加我微信



点个在看结对编程一把



浏览 116
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报