百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

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

yuyutoo 2024-10-25 19:20 2 浏览 0 评论

作者 | 阿文

责编 | 屠敏

出品 | 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、接口的版本等等参数去进行校验保证接口的安全性。

相关推荐

jQuery VS AngularJS 你更钟爱哪个?

在这一次的Web开发教程中,我会尽力解答有关于jQuery和AngularJS的两个非常常见的问题,即jQuery和AngularJS之间的区别是什么?也就是说jQueryVSAngularJS?...

Jquery实时校验,指定长度的「负小数」,小数位未满末尾补0

在可以输入【负小数】的输入框获取到焦点时,移除千位分隔符,在输入数据时,实时校验输入内容是否正确,失去焦点后,添加千位分隔符格式化数字。同时小数位未满时末尾补0。HTML代码...

如何在pbootCMS前台调用自定义表单?pbootCMS自定义调用代码示例

要在pbootCMS前台调用自定义表单,您需要在后台创建表单并为其添加字段,然后在前台模板文件中添加相关代码,如提交按钮和表单验证代码。您还可以自定义表单数据的存储位置、添加文件上传字段、日期选择器、...

编程技巧:Jquery实时验证,指定长度的「负小数」

为了保障【负小数】的正确性,做成了通过Jquery,在用户端,实时验证指定长度的【负小数】的方法。HTML代码<inputtype="text"class="forc...

一篇文章带你用jquery mobile设计颜色拾取器

【一、项目背景】现实生活中,我们经常会遇到配色的问题,这个时候去百度一下RGB表。而RGB表只提供相对于的颜色的RGB值而没有可以验证的模块。我们可以通过jquerymobile去设计颜色的拾取器...

编程技巧:Jquery实时验证,指定长度的「正小数」

为了保障【正小数】的正确性,做成了通过Jquery,在用户端,实时验证指定长度的【正小数】的方法。HTML做成方法<inputtype="text"class="fo...

jquery.validate检查数组全部验证

问题:html中有多个name[],每个参数都要进行验证是否为空,这个时候直接用required:true话,不能全部验证,只要这个数组中有一个有值就可以通过的。解决方法使用addmethod...

Vue进阶(幺叁肆):npm查看包版本信息

第一种方式npmviewjqueryversions这种方式可以查看npm服务器上所有的...

layui中使用lay-verify进行条件校验

一、layui的校验很简单,主要有以下步骤:1.在form表单内加上class="layui-form"2.在提交按钮上加上lay-submit3.在想要校验的标签,加上lay-...

jQuery是什么?如何使用? jquery是什么功能组件

jQuery于2006年1月由JohnResig在BarCampNYC首次发布。它目前由TimmyWilson领导,并由一组开发人员维护。jQuery是一个JavaScript库,它简化了客户...

django框架的表单form的理解和用法-9

表单呈现...

jquery对上传文件的检测判断 jquery实现文件上传

总体思路:在前端使用jquery对上传文件做部分初步的判断,验证通过的文件利用ajaxFileUpload上传到服务器端,并将文件的存储路径保存到数据库。<asp:FileUploadI...

Nodejs之MEAN栈开发(四)-- form验证及图片上传

这一节增加推荐图书的提交和删除功能,来学习node的form提交以及node的图片上传功能。开始之前需要源码同学可以先在git上fork:https://github.com/stoneniqiu/R...

大数据开发基础之JAVA jquery 大数据java实战

上一篇我们讲解了JAVAscript的基础知识、特点及基本语法以及组成及基本用途,本期就给大家带来了JAVAweb的第二个知识点jquery,大数据开发基础之JAVAjquery,这是本篇文章的主要...

推荐四个开源的jQuery可视化表单设计器

jquery开源在线表单拖拉设计器formBuilder(推荐)jQueryformBuilder是一个开源的WEB在线html表单设计器,开发人员可以通过拖拉实现一个可视化的表单。支持表单常用控件...

取消回复欢迎 发表评论: