杂谈
最近数据安全非常的火,由此衍生的API安全成为了很多人的焦点,由此,我们最近会通过视频讲解、图文讲解的形式带大家来了解API。
视频讲解
本期视频我们将从API的发展史,给大家梳理SOAP、RPC、REST、GraphQL常见的这四种API通讯方式,它们各有哪些优势?后出的就一定比之前的要好吗?
API发展史
![图片[1]-常见的四种API:SOAP vs RPC vs REST vs GraphQL-FancyPig's blog](https://www.cvv-goods.com/wp-content/uploads/2023/03/20221104103815769-1024x902-1.webp)
主流API技术
Request-Response Api
- RPC(Remote Procedure Call)
- Soap(Simple Object Acess Protocols)
- REST(Representational State Transfer)
- GraphQL
EDA(Event-Driven Architecture) Api
- Webhook
API对比
对比 | RPC | Soap | REST | GraphQL |
---|---|---|---|---|
发行时间 | 1998年XML-RPC 2005年JSON-RPC 2016年gRPC |
1999年 | 2000年 | 2015年 |
支持格式 | JSON,XML,Protobuf, Thrift,Flatbuffers |
仅支持XML | XML,JSON,HTML, 纯文本 |
JSON |
上手难度 | 简单 | 困难 | 简单 | 中等 |
社区 | 大 | 小 | 大 | 成长中 |
应用场景 | 支付网关 身份管理 客户关系管理解决方案 金融和电信服务 遗留系统支持 |
公共API 简单的资源驱动型应用程序 |
移动APIS 复杂的系统 微服务 |
指挥和行动导向的API 大规模微服务系统中的高性能通信 |
由于主要研究的是网络安全,故我们可能更关注于请求方式、请求体中的特征是怎样的?因此,下面会着重介绍这些特征,优势和缺点我们在这里不做重点叙述。
RPC
XML-RPC
如果你对此不太了解,你可以尝试在线调试
请求方式
GET
或者POST
举例
比方说,我们这里就拿wordpress举例,wordpress就是支持XML的,那如果我们想要获取wordpress下面有哪些接口,可以先通过POST
请求/xmlrpc.php
,请求体如下
<?xml version='1.0'?>
<methodCall>
<methodName>system.listMethods</methodName>
</methodCall>
然后就可以看到wordpress系统中有哪些方法
<methodResponse>
<params>
<param>
<value>
<array><data>
<value>
<string>system.multicall</string>
</value>
<value>
<string>system.listMethods</string>
</value>
<value>
<string>system.getCapabilities</string>
</value>
<value>
<string>demo.multiplyTwoNumbers</string>
</value>
<value>
<string>demo.addTwoNumbers</string>
</value>
<value>
<string>demo.sayHello</string>
</value>
<value>
<string>pingback.extensions.getPingbacks</string>
</value>
<value>
<string>pingback.ping</string>
</value>
<value>
<string>mt.publishPost</string>
</value>
<value>
<string>mt.getTrackbackPings</string>
</value>
<value>
<string>mt.supportedTextFilters</string>
</value>
<value>
<string>mt.supportedMethods</string>
</value>
<value>
<string>mt.setPostCategories</string>
</value>
<value>
<string>mt.getPostCategories</string>
</value>
<value>
<string>mt.getRecentPostTitles</string>
</value>
<value>
<string>mt.getCategoryList</string>
</value>
<value>
<string>metaWeblog.getUsersBlogs</string>
</value>
<value>
<string>metaWeblog.setTemplate</string>
</value>
<value>
<string>metaWeblog.getTemplate</string>
</value>
<value>
<string>metaWeblog.deletePost</string>
</value>
<value>
<string>metaWeblog.newMediaObject</string>
</value>
<value>
<string>metaWeblog.getCategories</string>
</value>
<value>
<string>metaWeblog.getRecentPosts</string>
</value>
<value>
<string>metaWeblog.getPost</string>
</value>
<value>
<string>metaWeblog.editPost</string>
</value>
<value>
<string>metaWeblog.newPost</string>
</value>
<value>
<string>blogger.deletePost</string>
</value>
<value>
<string>blogger.editPost</string>
</value>
<value>
<string>blogger.newPost</string>
</value>
<value>
<string>blogger.setTemplate</string>
</value>
<value>
<string>blogger.getTemplate</string>
</value>
<value>
<string>blogger.getRecentPosts</string>
</value>
<value>
<string>blogger.getPost</string>
</value>
<value>
<string>blogger.getUserInfo</string>
</value>
<value>
<string>blogger.getUsersBlogs</string>
</value>
<value>
<string>wp.getCommentStatusList</string>
</value>
<value>
<string>wp.newComment</string>
</value>
<value>
<string>wp.editComment</string>
</value>
<value>
<string>wp.deleteComment</string>
</value>
<value>
<string>wp.getComments</string>
</value>
<value>
<string>wp.getComment</string>
</value>
<value>
<string>wp.setOptions</string>
</value>
<value>
<string>wp.getOptions</string>
</value>
<value>
<string>wp.getPageTemplates</string>
</value>
<value>
<string>wp.getPageStatusList</string>
</value>
<value>
<string>wp.getPostStatusList</string>
</value>
<value>
<string>wp.getCommentCount</string>
</value>
<value>
<string>wp.uploadFile</string>
</value>
<value>
<string>wp.suggestCategories</string>
</value>
<value>
<string>wp.deleteCategory</string>
</value>
<value>
<string>wp.newCategory</string>
</value>
<value>
<string>wp.getTags</string>
</value>
<value>
<string>wp.getCategories</string>
</value>
<value>
<string>wp.getAuthors</string>
</value>
<value>
<string>wp.getPageList</string>
</value>
<value>
<string>wp.editPage</string>
</value>
<value>
<string>wp.deletePage</string>
</value>
<value>
<string>wp.newPage</string>
</value>
<value>
<string>wp.getPages</string>
</value>
<value>
<string>wp.getPage</string>
</value>
<value>
<string>wp.getUsersBlogs</string>
</value>
</data></array>
</value>
</param>
</params>
</methodResponse>
通过观察,我们可以看到有wp.getUserBlogs
方法,那我们如何通过这个方法,对用户名、密码进行暴力破解呢?
我们可以POST
请求,发送下面的内容,username
、password
分别代表用户名、密码,由此你也可以使用fuzz模糊测试或者burpsuite对其进行暴力破解,这也是为什么很多wordpress网站需要对xmlrpc.php
进行防护,甚至很多人在配置文件里将其关闭。
<?xml version='1.0'?>
<methodCall>
<methodName>wp.getUserBlogs</methodName>
<params>
<param>
<value>username</value>
</param>
<param>
<value>password</value>
</param>
</params>
</methodCall>
JSON-RPC
如果你对此不太了解,你可以尝试在线调试。如果你之前对区块链有所耳闻,其实大多数的挖矿都是通过JSON-RPC进行请求的,我们还可以看上次我分析的文章
请求方式
GET
或POST
举例
这里继续拿wordpress进行举例,下面是一个遐想的场景哦!仅用作和XML-RPC进行对比!
我们如果用JSON-RPC的方式请求刚才的接口,请求体的内容又是怎样的呢?
比方说,我们还是想获取系统下有哪些方法,那我们需要进行如下请求
{
"methodCall": {
"methodName": "system.listMethods",
}
}
那如果获取到了wp.getUserBlogs
,如何使用用户名、密码登录呢?
{
"methodCall": {
"methodName": "wp.getUserBlogs",
"params": [
{
username,
password
}
]
}
}
SOAP
请求方式
GET
或者POST
请求体格式
POST请求都应该有哪些内容呢?格式如下
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope/"
soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
<soap:Header>
...
</soap:Header>
<soap:Body>
...
<soap:Fault>
...
</soap:Fault>
</soap:Body>
</soap:Envelope>
举例
请求URL/getAdUnitsByStatement
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
xmlns:soapenv="https://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="https://www.w3.org/2001/XMLSchema"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<ns1:RequestHeader
soapenv:actor="https://schemas.xmlsoap.org/soap/actor/next"
soapenv:mustUnderstand="0"
xmlns:ns1="https://www.google.com/apis/ads/publisher/v201605">
<ns1:networkCode>123456</ns1:networkCode>
<ns1:applicationName>DfpApi-Java-2.1.0-dfp_test</ns1:applicationName>
</ns1:RequestHeader>
</soapenv:Header>
<soapenv:Body>
<getAdUnitsByStatement xmlns="https://www.google.com/apis/ads/publisher/v201605">
<filterStatement>
<query>WHERE parentId IS NULL LIMIT 500</query>
</filterStatement>
</getAdUnitsByStatement>
</soapenv:Body>
</soapenv:Envelope>
我们可以看到上面的其实核心就查询语句
<query>WHERE parentId IS NULL LIMIT 500</query>
对比JSON-RPC
,我们会发现上面属实繁琐太多了
下面是JSON-RPC的请求体部分
{"filter": "WHERE parentId IS NULL LIMIT 500"}
完整的POST请求包
POST /getAdUnitsByStatement HTTP/1.1
HOST: api.example.com
Content-Type: application/json
{"filter": "WHERE parentId IS NULL LIMIT 500"}
REST
请求方式
HEAD
或者GET
或者POST
或者PUT
或者PATCH
或者Delete
请求方式 | 作用 |
---|---|
HEAD | 对任何资源仅请求头信息 |
GET | 获取资源 |
POST | 创建资源 |
PATCH | 使用部分的JSON数据更新资源 |
PUT | 取代资源或资源集合 |
DELETE | 删除资源 |
状态码
状态码 | 描述 |
---|---|
200 OK | 表示请求已经成功。 |
201 Created | 表示请求已经成功,并因此创建了一个新的资源。 |
202 Accepted | 表示已经收到请求但尚未完成。它通常用于日志运行请求和批处理。 |
203 Non-Authoritative Information | 表示返回的实体头中的元信息不是来自源服务器的确定集合,而是从本地或第三方的副本中收集的。提出的集合可能是原始版本的子集或超集。 |
204 No Content | 服务器已经完成了请求,但不需要返回响应体。服务器可以返回更新的元信息。 |
205 Reset Content | 表示客户端要重置发送此请求的文件。 |
206 Partial Content | 当客户端发送Range 头时,它被用于只请求一个资源的一部分。 |
207 Multi-Status (WebDAV) | 给客户的一个指示器,表明发生了多个操作,每个操作的状态都可以在响应的正文中找到。 |
208 Already Reported (WebDAV) | 允许客户端告诉服务器相同的资源(具有相同的绑定)在前面被提及。它从不作为真正的HTTP响应代码出现在状态行中,而只出现在正文中。 |
226 IM Used | 服务器已经完成了对该资源的GET请求,并且响应是应用于当前实例的一个或多个实例处理结果的表示。 |
举例
请求URL
这里以某网站的API进行举例说明
请求方式 | URL | API 作用 |
---|---|---|
GET | /api/users?page=2 | 列出用户列表 |
GET | /api/users/2 | 查看某个用户信息 |
POST | /api/users/ | 创建用户 |
PUT | /api/users/ | 更新用户 |
PATCH | /api/users/ | 更新用户 |
DELETE | /api/users/ | 删除用户 |
请求体
如果是PUT
、PATCH
、POST
请求
URL为/api/user
{
"name": "morpheus",
"job": "leader"
}
总结
我们会发现请求体中也是JSON的格式,其实与JSON-RPC很像,但是这里REST风格的URL让人更容易理解了
GraphQL
请求方式
GET
或者POST
举例
我们这里可以使用一个测试站点
https://countries.trevorblades.com/
然后编写我们的查询语句
上面两个在线测试站点均可以完成,我们这里使用下面的语句,尝试第一次查询
query {
countries {
name
}
}
![图片[2]-常见的四种API:SOAP vs RPC vs REST vs GraphQL-FancyPig's blog](https://www.cvv-goods.com/wp-content/uploads/2023/03/20221104111625437-1024x507-1.webp)
![图片[3]-常见的四种API:SOAP vs RPC vs REST vs GraphQL-FancyPig's blog](https://www.cvv-goods.com/wp-content/uploads/2023/03/20221104111552664-1024x795-1.webp)
这里你可能会有疑问,就是在真正的请求中是怎样的呢?通常GraphQL和REST都会有一个端点,譬如/graphql
我们这里以GET
请求为例,则应该是https://countries.trevorblades.com/?query={countries{name}}
这里,我可能讲解的不够细致,详细的可以参考
GrphQL官网的讲解:https://graphql.cn/learn/serving-over-http/
暂无评论内容