热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

​如何设计一个安全可靠的API接口?

作者|阿文责编|屠敏出品|CSDN(ID:CSDNnews)最近几年,随着RESTfulAPI开始风靡,使用H

作者 | 阿文

责编 | 屠敏

出品 | CSDN(ID:CSDNnews)

最近几年,随着RESTful API开始风靡,使用HTTP header来传递认证令牌似乎变得理所应当,通过 RESTful 的API 接口设计简化了系统架构, 减少了耦合性, 可以让所有模块各自独立的进行改进。

不过,在实际的REST API 接口设计过程中,我们需要考虑如何让鉴权变得更安全可靠,例如不会被第三方恶意请求或者保证传输过程中的数据安全以及防止重复提交,本文就一起聊一聊。

传统的Session 认证方式

首先,我们说一些传统的认证方式,众所周知,HTTP 协议是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证,那么下一次请求时,用户还要再一次进行用户认证才行,因为我们并不能知道是哪个用户发出的请求,所以为了让我们的应用能识别是哪个用户发出的请求,我们只能在服务器存储一份用户登录的信息,这份登录信息会在响应时传递给浏览器,告诉其保存为COOKIE,以便下次请求时发送给我们的应用,这样我们的应用就能识别请求来自哪个用户了,这就是传统的基于session认证。

而这种方式有很多问题:

首先,占用资源,这种方式需要每个用户经过认证之后,都要在服务端做一次记录,以方便用户下次请求的鉴别,通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大。

其次,扩展性差: 客户端认证之后,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,在一些分布式的场景下会限制了负载均衡器的能力,会限制了应用的扩展能力。

第三,容易遭受攻击: 这种基于COOKIE来进行用户识别的认证方式, 很容易被截获,用户就会很容易受到跨站请求伪造的攻击。

基于Token 的鉴权方式

由于session 认证的诸多问题,因此出现了基于token 的鉴权方式,这种方式不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利。

基于token 鉴权的工作流程如下:

  • 首先,客户端通过用户名密码来请求对应的API接口

  • 第二,服务器会验证用户的信息

  • 第三,服务器通过验证后会发送token给客户端

  • 第四,客户端存储token,并在每次请求时附送上这个token值

  • 第五,服务端验证token值,并返回数据

这种方式的典型代表就是JWT(Json web token , 它是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519),该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

它的特点如下:

  • 体积小(一串字符串)。因而传输速度快

  • 传输方式多样。可以通过 HTTP 头部(推荐)/URL/POST 参数等方式传输

  • 严谨的结构化。它自身(在 payload 中)就包含了所有与用户相关的验证消息,如用户可访问路由、访问有效期等信息,服务器无需再去连接数据库验证信息的有效性,并且 payload 支持应用定制

  • 支持跨域验证,多应用于单点登录

JWT通常由三部分组成:

  • 头信息(header)

  • 消息体(payload)

  • 签名(signature)

如下所示:

// Header { "alg": "HS256", "typ": "JWT" }// Payload { // reserved claims "iss": "a.com", "exp": "1d", // public claims "http://a.com": true, // private claims "company": "A", "awesome": true }// $Signature HS256(Base64(Header) + "." + Base64(Payload), secretKey)// JWT JWT = Base64(Header) + "." + Base64(Payload) + "." + $Signature 

其工作流程如下:

  • 首先,客户端通过发送HTTP 请求把账号密码发送给服务短,通常使用的是POST请求, 服务器会校验账号与密码是否合法,如果一致,则根据密钥生成一个 token 并返回,客户端收到这个 token 并保存在本地。在这之后,需要访问一个受保护的路由或资源时,只要附加上 token(通常使用 Header 的 Authorization 属性)发送到服务器,服务器就会检查这个 token 是否有效,并做出响应。

  • 服务端接收到 token 之后,会逆向构造过程,解码出 JWT 的三个部分,这一步可以得到 sign 的算法及 payload,结合服务端配置的 secretKey,可以再次进行 $Signature 的生成得到新的 $Signature,与原有的 $Signature 比对以验证 token 是否有效,完成用户身份的认证,验证通过才会使用 payload 的数据。

如何保证接口安全性

要想实现接口的安全性,我们可以做到以下几点:

首先,我们需要采用HTTPS 对传输过程中的数据进行加密,避免使用HTTP 这种明文传输的协议,防止数据直接暴露在公网中,在使用HTTPS的同时要保证时间安全可靠的加密方法和SSL 协议,目前主流的是TLS1.2 和最新的TLS1.3。同时要对证书进行校验,因为即使是HTTPS协议,证书也是能够被伪造的。

其次,对接口设计一般会加入 token、timestamp和sign 这些参数,不同的参数有自己不同的用途:

  • timestamp,即时间戳,它是客户端调用接口时传入的当前时间戳,时间戳的目的是用于防止DoS攻击。每次调用接口时接口都会判断服务器当前系统时间和接口中传的的timestamp的差值,如果这个差值超过某个设置的时间,例如设置的时间是3分钟,那么这个请求将被拦截掉,如果在设置的超时时间范围内,是不能阻止DoS攻击的。timestamp机制只能减轻DoS攻击的时间,缩短攻击时间。如果黑客修改了时间戳的值可通过sign签名机制来处理。

  • sign,即签名,通常用于参数签名,防止参数被非法篡改,最常见的是修改金额等重要敏感参数, sign的值一般是将所有非空参数按照升续排序然后+token+key+timestamp+nonce(随机数)拼接在一起,然后使用某种加密算法进行加密,这种方式的好处就是,当被劫持后,修改其中的参数值,然后再继续调用接口,虽然参数的值被修改了,但是因为攻击者并不清楚sign是如何计算出来的,所以即可是篡改参数的值,但没法修改sign的值,当服务器调用接口前会按照sign的规则重新计算出sign的值然后和接口传递的sign参数的值做比较,如果相等表示参数值没有被篡改,如果不等,表示参数被非法篡改了,则不会返回真实的响应信息。

  • 此外,接口设计时候要实现幂等性操作,所谓的幂等性操作就是为了防止重复性运算,我们可以将生成的签名和key保存到redis 中,并且设置超时时间,过期自动删除,当有重复的值存在则不会处理,就可以防止重复提交,从而保证请求结果一致性。

其使用流程如下:

  1. 接口调用方(客户端)向接口提供方(服务器)申请接口调用账号,申请成功后,接口提供方会给接口调用方一个AppKey和一个APP Secret参数

  2. 调用方申请App Key 和 App Secret 在生成请求时,将参数拼接后进行加密,例如使用HMAC-SHA256 或MD5加密,然后将 App Key, 加密结果追加到请求上。sign=加密(appId + timestamp + key)

  3. 服务收到请求后,根据App Key识别出调用方,解密得到参数以及对时间进行对比,判断是否超时,然后从字典中查询到对应的App Secret,与请求参数拼接、加密,与请求中的签名进行对比,签名结果相同的为合法请求。

以上就是给API 接口设计的一些建议,仅供参考,在实际的应用中还可以追加一些公共的参数,例如Host、接口的版本等等参数去进行校验保证接口的安全性。

更多精彩推荐
☞马斯克身家超马云,网友:看完他的履历后一点也不惊讶
☞31 道 Java 核心面试题,统统打包给你!
☞阿里回应被列为被执行人;Linus Torvalds:我已经不是程序员;Ant Design 4.4.1 发布 | 极客头条
☞看懂别人的代码,只是成为高效程序员的第一步!
☞用Python轻松搞定Excel中的20个常用操作
☞孟岩:从DeFi内卷式发展看数字资产的意义
点分享点点赞点在看


推荐阅读
  • 4种分布式Session的实现方式!老大直呼666...
    前言公司有一个Web管理系统,使用Tomcat进行部署。由于是后台管理系统,所有的网页都需要登录授权之后才能进行相应的操作。起初这个系统的用的人也不多& ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 14亿人的大项目,腾讯云数据库拿下!
    全国人 ... [详细]
  • adfs是什么_培训与开发的概念
    adfs是什么_培训与开发的概念(如您转载本文,必须标明本文作者及出处。如有任何疑问请与我联系me@nap7.com)ADFS相关开发技术的中文资料相对匮乏,之前在弄这个东西的时候 ... [详细]
  • 单点登录原理及实现方案详解
    本文详细介绍了单点登录的原理及实现方案,其中包括共享Session的方式,以及基于Redis的Session共享方案。同时,还分享了作者在应用环境中所遇到的问题和经验,希望对读者有所帮助。 ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
    在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
  • ElasticSerach初探第一篇认识ES+环境搭建+简单MySQL数据同步+SpringBoot整合ES
    一、认识ElasticSearch是一个基于Lucene的开源搜索引擎,通过简单的RESTfulAPI来隐藏Lucene的复杂性。全文搜索,分析系统&# ... [详细]
  • 云原生应用最佳开发实践之十二原则(12factor)
    目录简介一、基准代码二、依赖三、配置四、后端配置五、构建、发布、运行六、进程七、端口绑定八、并发九、易处理十、开发与线上环境等价十一、日志十二、进程管理当 ... [详细]
  • [翻译]微服务设计模式5. 服务发现服务端服务发现
    服务之间需要互相调用,在单体架构中,服务之间的互相调用直接通过编程语言层面的方法调用就搞定了。在传统的分布式应用的部署中,服务地 ... [详细]
  • 服务网关与流量网关
    一、为什么需要服务网关1、什么是服务网关传统的单体架构中只需要开放一个服务给客户端调用,但是微服务架构中是将一个系统拆分成多个微服务,如果没有网关& ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • Java和JavaScript是什么关系?java跟javaScript都是编程语言,只是java跟javaScript没有什么太大关系,一个是脚本语言(前端语言),一个是面向对象 ... [详细]
  • ejava,刘聪dejava
    本文目录一览:1、什么是Java?2、java ... [详细]
author-avatar
XC一米_623
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有