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

安全优雅的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

时间: 2024-11-13 08:45:10

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

(转) SpringBoot非官方教程 | 第十一篇:springboot集成swagger2,构建优雅的Restful API

swagger,中文"拽"的意思.它是一个功能强大的api框架,它的集成非常简单,不仅提供了在线文档的查阅,而且还提供了在线文档的测试.另外swagger很容易构建restful风格的api,简单优雅帅气,正如它的名字. 一.引入依赖 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <vers

【重播工具箱】MTK全方案手机端APP,一键备份自动生成线刷包 源码思路解析

这个是本人MTK工具箱,在 5月份的时候,发布的..功能可能说是全球首发把,第一个手机MTK的一键备份工具,而且是兼容MTK全方案.MTK6589 MTK6592 6575 82等, 现在将源码以及思路,分享给大家,有兴趣的可以看看. 源码解析以及思路,待发布....... 分享地址:http://www.592zn.com/thread-311286-1-1.html 下载地址http://pan.baidu.com/s/1hqeethy重大更新: 1.手机端首发,备份MTK系列全自动,生成线

企业级 SpringBoot 教程 (十一)springboot集成swagger2,构建优雅的Restful API

swagger,中文"拽"的意思.它是一个功能强大的api框架,它的集成非常简单,不仅提供了在线文档的查阅,而且还提供了在线文档的测试.另外swagger很容易构建restful风格的api,简单优雅帅气,正如它的名字. 一.引入依赖 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <vers

JAVA springboot微服务b2b2c电子商务系统-springboot集成swagger2,构建优雅的Restful API(十一)

swagger,中文"拽"的意思.它是一个功能强大的api框架,它的集成非常简单,不仅提供了在线文档的查阅,而且还提供了在线文档的测试.另外swagger很容易构建restful风格的api,简单优雅帅气,正如它的名字. 一.引入依赖 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <vers

开放接口/RESTful/Api服务的设计和安全方案

总体思路 这个涉及到两个方面问题:一个是接口访问认证问题,主要解决谁可以使用接口(用户登录验证.来路验证)一个是数据数据传输安全,主要解决接口数据被监听(HTTPS安全传输.敏感内容加密.数字签名) 用户身份验证:Token与Session开放接口Api服务其实就是客户端与服务端无状态交互的一种形式,这有点类似REST(Representational State Transfer)风格.普通网站应用一般使用session进行登录用户信息的存储和验证(有状态),而开放接口服务/REST资源请求则

构建自描述 RESTFul API 体系的设计与畅想

今天的互联网世界,API 已经无处不在,越来越多的服务依赖 API 交换信息,彼此协作,彼此连接,API 开发协作的体验也越来越重要. 有协作,就有沟通,显而易见的方法就是写文档,用文档描述 API 的用途,使用方法.但如何保持文档与代码的同步确是业界的千古难题,能做得到位的寥寥无几. 难道就真的没有方法了吗? 这就是本文的主题,构建自描述 RESTFul API 体系,如何通过自描述的 API 设计,抹除代码与文档的界限,一切皆代码. 何谓自描述 所谓的自描述,就是让 API 在提供具体的功能

RESTful API 设计最佳实践(转)

摘要:目前互联网上充斥着大量的关于RESTful API(为了方便,以后API和RESTful API 一个意思)如何设计的文章,然而却没有一个”万能“的设计标准:如何鉴权?API格式如何?你的API是否应该加入版本信息? 背景 目前互联网上充斥着大量的关于RESTful API(为了方便,以后API和RESTful API 一个意思)如何设计的文章,然而却没有一个”万能“的设计标准:如何鉴权?API格式如何?你的API是否应该加入版本信息?当你开始写一个app的时候,特别是后端模型部分已经写完

RESTful API 设计最佳实践

1. 背景 REST(英文:Representational State Transfer,表述性状态转移)描述了一个架构样式的网络系统,比如 web 应用程序. 目前互联网上充斥着大量的关于RESTful API(为方便,下文中"RESTful API "简写为"API")如何设计的文章,然而却没有一个"万能"的设计标准:如何鉴权?API 格式如何?你的API是否应该加入版本信息?当你开始写一个app的时候,特别是后端模型部分已经写完的时候,你

如何设计好的RESTful API之安全性

原文:http://blog.csdn.net/ywk253100/article/details/25654101 导读:安全是恒久的话题,对于基于WSDL和SOAP的Web Service,我们有WS-Security这样的安全规范来指导实现认证.授权.身份管理等安全需求.如何保证RESTful API的安全性呢. 关键词:RESTful API API安全性 前面讲了好的RESTful API具有的一些特征,本文会继续探讨RESTful API的安全性问题. InfoQ:安全是恒久的话题,