RESTful Api 身份认证安全性设计
REST是一种软件架构风格。RESTful Api 是基于 HTTP 协议的 Api,是无状态传输。它的核心是将所有的 Api 都理解为一个网络资源。将所有的客户端和服务器的状态转移(动作)封装到 HTTP 请求的 Method 之中。
详情可以阅读 http://mengkang.net/620.html 。
而这篇文章则主要是讨论 RESTful Api 身份认证安全性设计。
没有绝对的安全,这个话题很深, 下文都是自己的一些理解,水平有限,如有勘误,希望大家予以指正。
由于 RESTful Api 是基于 Http 协议的 Api,是无状态传输,所以 只要和用户身份有关的 请求 都会带上身份认证信息。(很多时候客户端事先并不知道某个 api 后期会不会加入身份判断,所以我们一般都会选择每个请求都会带上认证信息,如果有的话。)
Http Basic Authentication
Http Basic 是一种比较简单的身份认证方式。 在 Http header 中添加键值对 Authorization: Basic xxx (xxx 是 username:passowrd base64 值)。
例如 username 为 zmk ,password 为 123456,请求则如下
GET /auth/basic/ HTTP/1.1
Host: xxxxx
Authorization: Basic em1rOjEyMzQ1Ng==
而Base64 的解码是非常方便的,如果不使用 Https ,相当于是帐号密码直接暴露在请求中。
危险性高,实际开发者使用的应该几乎为0。
顺便提下 DIGEST 认证,和 BASIC 认证相差无几,而且不适合 api 设计,实际又需要两次请求,首次请求,服务器端返回401,并且带上 nonce 值,然后客户端再利用 username + password + nonce 默认MD5之后再请求。对 http 请求的作用是仅仅防止二次请求,对身份认证并没有什么提升。
Cookie + Session
不知道是否应该这么称呼,只是觉得类似于 cookie 与 session 的机制。
原理即当客户端登录完毕之后,给客户端返回一个 cookie ,服务器端控制该 session 的有效期, 每次请求都带上该值,然后服务器端做验证,退出之后,客户端通知服务端端销毁 session ,自身销毁 cookie 。但是如果抓包获取到 cookie ,就能任意伪造请求了。
危险性高,实际开发估计使用得还不少。
Api Key + Security Key + Sign
下图是我们自己每次请求的身份认证的方式,如有不足,请大家指出。可以说是 JWT 的自定义版吧。

这里的认证逻辑即:
用户登录返回一个 api_key 和 security_key ;
然后客户端将 security_key 存在客户端;
当要发送请求之前,通过 function2 加密方法,把如图所示的五个值一起加密,得到一个 sign ;
发送请求的时候,则将除去 security_key 之外的值,以及 sign 一起发送给服务器端;
服务器端首先验证时间戳是否有效,比如是服务器时间戳5分钟之前的请求视为无效;
然后根据 api_key 验证 sercurity_key ;
最后验证 sign 。
是否需要加上时间戳验证?
上面的认证逻辑中加密得到签名的时候,把时间戳加进去是为了在一定程度上屏蔽了一些无效的请求,可以略去,也可以设计的更加严格。 如果想防止恶意的 api ddos 攻击,这一步验证肯定是不行的。需要做更多的验证,比如用户验证,ip 验证等。 可以参考 github 的 api 的设计 。它会在返回的 http 头信息里带上
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4999
表示这个接口在某一时间段内,该授权用户调用该接口的最大次数为5000次,该时间段内还剩余4999次。当然,这样的验证加上之后,在代码的执行效率上肯定会有所影响。
是否需要将 request_parameters 也加入到 sign 生成的算法之中?
也不是必须的,仅仅是为了请求的真实性,减少请求的伪造,比如 有人抓包拿到 http 请求之后,如果没有验证 sign 这步,那么别人就可以非常简单的修改请求的参数,而请求都会生效。
血的教训,自己经历的一个实际案例:
一个取消用户喜欢的标签的接口,该接口会向服务器端发送类似于 ids=1,2,3,4 这样的 request_parameters ,然后服务器端拿到这些 id 之后切割,然后将该用户和这些标签的关系从 user_tag 表中删除。某个周末,数据库服务器报警,而依照我们用户习惯,那个时间不存在流量高峰,这个报警很不正常,正准备处理,报警结束了,但是过了一段时间就有用户反应他们喜欢的标签都被删了。
通过查询数据库的慢日志,发现有很多注入的 sql。
DELETE FROM `user_tag` WHERE uid=4385328 AND tid=1 OR 14=14;
DELETE FROM `user_tag` WHERE uid=4385328 AND tid=1 OR 91=91;
原来 没有对切割之后的 id 没有做数字验证,估计黑客就是传的 ids=1 OR 14=14,2,3 ,而一个 delete 操作可能超时,他丫的就搞了很多次请求,真是够狠的。
幸运,数据库还有定时的打包备份,大部分用户的数据还是恢复了,同时修复了这一漏洞。
所以如果这里将 request_parameters 也加入到签名之中,就减少了伪造请求的可能性,但是无法杜绝,破坏者可能就非要黑你,又对逆向工程非常熟悉,找到我们加密算法的实现,依然可以未知出合法的签名,所以我们常说,服务器端永远不能相信客户端的请求都是安全的、合法的,需要做验证的都还是不能省略。
同时这( sign 算法)也造成了 api 接口调试的成本,api 测试工具必须也得实现那一套算法,或者是设置在开发环境下不做验证。我们在配置开发环境的时候则是 vpn 连测试服务器所在内网,然后进行测试,否则开发环境也存在被人利用的风险。
JWT
JWT ( JSON Web Token ) 使用流程如下(图片来自官网)

其认证机制也是登录,发放密钥给客户端, 然后客户端每次发送请求的时候通过 JWT 的算法规则组装 JWT 的 Auth Header ,服务器端作验证。
web 授权认证的原理万变不离其宗,都是如此。
只不过 JWT 呢,自定了一套认证协议。格式为 Header . Payload . Signature 。比如 xxxxx.yyyyy.zzzzz 。签名内容是有 Header + Payload + Secret 通过 HMAC SHA256 算法加密而成。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
而请求的很多参数键值对都可以放在 Payload 里面。完整讲解请求看官方的介绍 http://jwt.io/introduction/
需要注意的一点 ,依照 JWT 的协议,只有一个 secret ,无法得知该用户是谁,所以在 secret 该值中必须要可以解码出用户的id。
而我们自定义认证协议的时候 header 感觉就没有必要了,使用什么算法事先定义好即可。所以我们也没选择这种方式而是上面的那种方式。
一个基于 netty 的严格的安全验证的轻量级的 RESTful Api Serverhttps://github.com/zhoumengkang/netty-restful-server
来自: http://mengkang.net/625.html
RESTful Api 身份认证安全性设计的更多相关文章
- RESTful Api 身份认证中的安全性设计探讨
REST 是一种软件架构风格.RESTful Api 是基于 HTTP 协议的 Api,是无状态传输.它的核心是将所有的 Api 都理解为一个网络资源.将所有的客户端和服务器的状态转移(动作)封装到 ...
- 关于RESTFUL API 安全认证方式的一些总结
常用认证方式 在之前的文章REST API 安全设计指南与使用 AngularJS & NodeJS 实现基于 token 的认证应用两篇文章中,[译]web权限验证方法说明中也详细介绍,一般 ...
- 关于 RESTFUL API 安全认证方式的一些总结
常用认证方式 在之前的文章REST API 安全设计指南与使用 AngularJS & NodeJS 实现基于 token 的认证应用两篇文章中,[译]web权限验证方法说明中也详细介绍,一般 ...
- 基于token的多平台身份认证架构设计
基于token的多平台身份认证架构设计 1 概述 在存在账号体系的信息系统中,对身份的鉴定是非常重要的事情. 随着移动互联网时代到来,客户端的类型越来越多, 逐渐出现了 一个服务器,N个客户端的格 ...
- WebApi 基于token的多平台身份认证架构设计
1 概述 在存在账号体系的信息系统中,对身份的鉴定是非常重要的事情. 随着移动互联网时代到来,客户端的类型越来越多, 逐渐出现了 一个服务器,N个客户端的格局 . 不同的客户端产生了不同的用户使用 ...
- RESTful API后台系统架构设计(Java)
最近设计和实现了一个JAVA的RESTful API的后台业务系统架构,主要基于Java平台.设计要求是: 性能:平均响应时间(RESTful API)小于2s(平均负载的情况下),并发访问200个以 ...
- 基于Token的多平台身份认证价格设计
1 概述 在存在账号体系的信息系统中,对身份的鉴定是非常重要的事情. 随着移动互联网时代到来,客户端的类型越来越多, 逐渐出现了 一个服务器,N个客户端的格局 . 不同的客户端产生了不同的用户使用 ...
- 基于Node的PetShop,RESTful API以及认证
前篇 - 基本认证,用户名密码 后篇 - OAuth2 认证 由于宠物店的业务发展需要,我们需要一种更加便捷的方式来管理日益增多的宠物和客户.最好的方法就是开发一个APP,我可以用这个APP来添加.更 ...
- Spring+SpringMVC+MyBatis+easyUI整合进阶篇(二)RESTful API实战笔记(接口设计及Java后端实现)
写在前面的话 原计划这部分代码的更新也是上传到ssm-demo仓库中,因为如下原因并没有这么做: 有些使用了该项目的朋友建议重新创建一个仓库,因为原来仓库中的项目太多,结构多少有些乱糟糟的. 而且这次 ...
随机推荐
- .NET开源进行时:消除误解、努力前行(本文首发于《程序员》2015第10A期的原始版本)
2014年11月12日,ASP.NET之父.微软云计算与企业级产品工程部执行副总裁Scott Guthrie,在Connect全球开发者在线会议上宣布,微软将开源全部.NET核心运行时,并将.NET ...
- 最牛的打字效果JS插件 typing.js
最新在做公司的一个项目,需要实现一个敲打代码的动画效果,粗意味比较简单,果断自己直接开写,写着写着发现是一个坑.需要支持语法高亮,并不能直接简单的用setTimeout来动态附件innerHTML.苦 ...
- nginx常用代理配置
因为业务系统需求,需要对web服务作nginx代理,在不断的尝试过程中,简单总结了一下常见的nginx代理配置. 1. 最简反向代理配置 在http节点下,使用upstream配置服务地址,使用ser ...
- jar hell & elasticsearch ik 版本问题
想给es 安装一个ik 的插件, 我的es 是 2.4.0, 下载了一个版本是 1.9.5, [2016-10-09 16:56:26,248][INFO ][node ] [node-2] init ...
- CentOS 6.6 升级GCC G++ (当前最新版本为v6.1.0) (完整)
---恢复内容开始--- CentOS 6.6 升级GCC G++ (当前最新GCC/G++版本为v6.1.0) 没有便捷方式, yum update.... yum install 或者 添加y ...
- 网站就必须用响应式布局吗?MVC视图展现模式之移动布局
本文先引入给读者一个自己研究的机会,下次深入说明一下: 废话不多说,直接上图 新建一个mvc的项目 在视图里面添加一个移动端视图 正常访问一下 Bootstrap自带的响应式的方式(页面代码并没有改变 ...
- ASP.NET 页面禁止被 iframe 框架引用
两个站点: a.sample.com b.sample.com a.sample.com 站点中的一段示例 JS 代码: var iframe = document.createElement(&qu ...
- 野路子出身PowerShell 文件操作实用功能
本文出处:http://www.cnblogs.com/wy123/p/6129498.html 因工作需要,处理一批文件,本想写C#来处理的,后来想想这个是PowerShell的天职,索性就网上各种 ...
- 你可曾见过如此简单粗暴的JavaScript解说 -- if 判断的正确打开方式?
在JavaScript中,对于 if else 的逻辑判断你肯定非常熟悉,本文罗列了几种你不一定知道的简写方式,仅供参考. 例子: 已知小明考了68分,小于60分为不及格,大于60分为及格,问:小明是 ...
- import matplolib 时出现"This probably means that tk wasn't installed properly."的解决方法
最近又添了一台新电脑,配置好各个依赖环境后想用matplotlib画个图,结果报出下面的错误 根据报错分析,应该是C:/Python27/tcl/tk8.5/tk.tcl这个文件出问题了,根据图中的信 ...