安全优雅的RESTful API签名实现方案

1、接口签名的必要性

在为第三方系统提供接口的时候,肯定要考虑接口数据的安全问题,比如数据是否被篡改,数据是否已经过时,数据是否可以重复提交等问题。其中我认为最终要的还是数据是否被篡改。在此分享一下我的关于接口签名的实践方案。

2、项目中签名方案痛点

  • 每个接口有各自的签名方案,不统一,维护成本较高。
  • 没有对消息实体进行签名,无法避免数据被篡改。
  • 无法避免数据重复提交。

3、签名及验证流程

4、签名规则

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

5、签名生成

5.1、数据部分

  • Path:按照path中的顺序将所有value进行拼接
  • Query:按照key字典序排序,将所有key=value进行拼接
  • Form:按照key字典序排序,将所有key=value进行拼接
  • Body:

    如果存在多种数据形式,则按照path、query、form、body的顺序进行再拼接,得到所有数据的拼接值。
    上述拼接的值记作 Y。

5.2、请求头部分

X="appid=xxxnonce=xxxtimestamp=xxx"

5.3、生成签名

最终拼接值=XY
最后将最终拼接值按照如下方法进行加密得到签名(signature)。

6、签名算法实现

6.1、指定哪些接口或者哪些实体需要签名

6.2、指定哪些字段需要签名

6.3、签名核心算法(SignatureUtils)

  • toSplice方法首先判断对象是否注有@Signature注解,如果有则获取签名的排序规则(key值字典序排序或者指定order的值进行排序),比如排序规则是Signature.ALPHA_SORT(字典序)会调用alphaSignature方法生成key=value的拼接串;如果对象没有@Signature注解,该对象类型可能是数组、者集合类等,则调用toString方法生成key=value的拼接串。
  • alphaSignature方法通过反射获取到对象的所有Field属性,需要判断两种情况:(1)获取该Field属性对应的Class信息,如果Class信息含有@Signature注解,则调用toSplice方法生成key=value的拼接串;(2)该Field属性含有@SignatureField注解,调用toString方法生成key=value的拼接串。
  • toString方法针对array, collection, simple property, map类型的数据做处理。其中如果对象是java的simple property类型,直接调用对象的toString方法返回value;如果是array、collection、map类型的数据,再调用toSplice方法生成key=value的拼接串。

7、签名校验

7.1、header中参数

7.2、签名实体SignatureHeaders, 绑定request中header信息

7.3、生成签名实体SignatureHeaders并验证


签名验证需要如下几个步骤。

  • 处理header name,通过工具类将header信息绑定到签名实体SignatureHeaders对象上。
  • 验证appid是否合法。
  • 根据appid从配置中心中拿到appsecret。
  • 请求是否已经超时,默认10分钟。
  • 随机串是否合法。
  • 是否允许重复请求。
  • 重新生成签名,验证签名是否一致。

7.4、生成header信息参数拼接

7.5、切面拦截控制层方法,生成method中参数的拼接


generateAllSplice方法是在控制层切面内执行,可以在方法执行之前获取到已经绑定好的入参。分别对注有@PathVariable、@RequestParam、@RequestBody、@ModelAttribute注解的参数进行参数拼接的处理。其中注@RequestParam注解的参数需要特殊处理一下,分别考虑数组、集合、原始类型这三种情况。

7.6、对最终的拼接结果重新生成签名信息

8、客户端使用示例

8.1、生成签名

8.2、输出结果

拼接结果: appid=111^_^appsecret=222^_^nonce=c9e778ba668c8f6fedf35634eb493af6304d54392d990262d9e7c1960b475b67^_^timestamp=1538207443910^_^w8rAwcXDxcDKwsM=^_^
签名数据: SignatureHeaders{appid=111, appsecret=222, timestamp=1538207443910, nonce=c9e778ba668c8f6fedf35634eb493af6304d54392d990262d9e7c1960b475b67, signature=0a7d0b5e802eb5e52ac0cfcd6311b0faba6e2503a9a8d1e2364b38617877574d}
请求数据: [w8rAwcXDxcDKwsM=]

9、思考

上述的签名方案的实现校验逻辑是在控制层的切面内完成的。如果项目用的是springmvc框架,可以放在Filter或者拦截器里吗?很明显是不行的(因为ServletRequest的输入流InputStream 在默认情况只能读取一次)。上述方案需要获取绑定后的参数结果,然后执行签名校验逻辑。在执行控制层方法之前,springmvc已经帮我们完成了绑定的步骤,当然了,在绑定的过程中会解析ServletRequest中参数信息(例如path参数、parameter参数、body参数)。

其实如果我们能在Filter或者拦截器中实现上述方案,那么复杂度将会大大的降低。首先考虑如何让ServletRequest的输入流InputStream可以多次读取,然后通过ServletRequest获取path variable(对应@PathVariable)、parameters(对应@RequestParam)、body(对应@RequestBody)参数,最后整体按照规则进行拼接并生成签名。

优化方案参考:https://www.cnblogs.com/hujunzheng/p/10178584.html

转载于:https://www.cnblogs.com/hjzgg/p/11066832.html

安全优雅的RESTful API签名实现方案(手机端)相关推荐

  1. springboot集成swagger2,构建优雅的Restful API

    springboot集成swagger2,构建优雅的Restful API 转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springboot/2017/07/ ...

  2. SpringBoot第十一篇:springboot集成swagger2,构建优雅的Restful API

    swagger,中文"拽"的意思.它是一个功能强大的api框架,它的集成非常简单,不仅提供了在线文档的查阅,而且还提供了在线文档的测试.另外swagger很容易构建restful风 ...

  3. php slim 教程,Slim - 超轻量级PHP Restful API构建框架

    下载源码包: http://www.slimframework.com/ 基于Slim的Restful API Sample: require '/darjuan/Slim/Slim.php'; us ...

  4. Restful API 中的错误处理方案

    简介 随着移动开发和前端开发的崛起,越来越多的 Web 后端应用都倾向于实现 Restful API. Restful API 是一个简单易用的前后端分离方案,它只需要对客户端请求进行处理,然后返回结 ...

  5. 让SpringMVC Restful API优雅地支持多版本

    好久没有更新博客,难得有空,记录一下今天写的一个小工具,供有需要的朋友参考. 在移动APP开发中,多版本接口同时存在的情况经常发生,通常接口支持多版本,有以下两种方式: 1.通过不同路径区分不同版本 ...

  6. post如何获取到referrer_如何使用 ThinkJS 优雅的编写 RESTful API

    RESTful 是目前比较主流的一种用来设计和编排服务端 API 的一种规范.在 RESTful API 中,所有的接口操作都被认为是对资源的 CRUD,使用 URI 来表示操作的资源,请求方法表示具 ...

  7. 视频教程-Ruby on Rails打造企业级RESTful API项目实战我的云音乐-Ruby/Rails

    Ruby on Rails打造企业级RESTful API项目实战我的云音乐 任苹蜻,爱学啊创始人 & CEO,曾就职于某二车手公司担任Android工程师后离职创办爱学啊,我们的宗旨是:人生 ...

  8. 我是如何根据豆瓣api来理解Restful API设计的

    1.什么是REST REST全称是Representational State Transfer,表述状态转移的意思.它是在Roy Fielding博士论文首次提出.REST本身没有创造新的技术.组件 ...

  9. RESTful API 设计最佳实践

    2019独角兽企业重金招聘Python工程师标准>>> 背景 目前互联网上充斥着大量的关于RESTful API(为方便,下文中"RESTful API "简写为 ...

  10. 人人都是 API 设计者:我对 RESTful API、GraphQL、RPC API 的思考

    有一段时间没怎么写文章了,今天提笔写一篇自己对 API 设计的思考.首先,为什么写这个话题呢?其一,我阅读了<阿里研究员谷朴:API 设计最佳实践的思考>一文后受益良多,前两天并转载了这篇 ...

最新文章

  1. Docker Swarm Mode 学习笔记(聊聊 replicas)
  2. springboot 拦截器 日志_跟武哥一起学习Spring Boot,一份全面详细的学习教程
  3. 虚拟环境vitualenv的使用
  4. 2021计算机专业考408的学校,2021考研:计算机考研408是什么?统考学校有哪些?...
  5. mybatis工作笔记002_mybatis中如果返回的结果没有的话默认返回null的list_但可启用returnInstanceForEmptyRow_返回为list不为null但为0条
  6. 【Docker】Redis 安装使用教程
  7. Windows 用户怒了!系统漏洞简直泛滥成灾
  8. C# 格式化json移除空值,参数按照第一个字符的键值 ASCII 码递增排序(SM2签名)
  9. 苹果app(iOS app)比较常用的URL schemes,可以用于iOS应用间相互调用
  10. PlatformIO中arduino框架下stm32编程实现原理
  11. 计算机除氧化的方法,内存条氧化了的解决方法
  12. 微信群发频繁发送消息,请稍后再试?
  13. 现代家用计算机有哪些名称,世界上第一台现代电子计算机是什么?
  14. golang并发http请求几种方式
  15. 固有的不可移植的特征之volatile限定符
  16. MySQL使用教程(Navicat)
  17. Ipopt with Metis编译指南
  18. Spark 学习【二】
  19. R语言ggplot2可视化:patchwork包将一个ggplot2可视化结果和一个plot函数可视化结果横向组合起来形成最终结果图、两个可视化的组合结果对齐、并为组合图像的每个子图添加标题
  20. 实战TSA与HADR

热门文章

  1. 华为跨域bgp_跨域组播---BGP+MSDP
  2. python aic准则_pythonAIC准则下线性回归实现及模型检验案例分析
  3. 摄影测量空间后方交会外方位元素的解算程序
  4. prometheus安装使用
  5. 计算机主机重装主机过程,电脑怎么重装系统步骤 超简单的电脑重装系统教程...
  6. 元胞自动机与疏散模型的matlab算法,元胞自动机模拟多出口疏散模型的matlab实现...
  7. JavaScript实现累加和累乘
  8. kafka-Streaming错误:在IDEA连接kafka时出现错误
  9. MongoDb(六)索引原理和命令
  10. 爬取人民日报_辅导员专栏 | 琪人琪语:我们爬取了576篇人民日报的夜读文章,只为告诉你这些事...