RESTful API 路径详解
RESTful API(Representational State Transfer)是一种 基于 HTTP 协议的 API 设计风格,它通过 URL 路径 和 HTTP 方法(GET、POST、PUT、DELETE 等)来定义资源的访问方式。它的核心思想是 将数据(资源)暴露为 URI(路径),并通过标准 HTTP 方法操作这些资源。
1. RESTful API 路径是什么?
RESTful API 路径(Endpoint)是一个 URL,用于访问服务器上的特定资源。它的结构通常遵循以下模式:
http(s)://域名/api/资源名/{资源ID}/子资源/{子资源ID}?查询参数
例如:
https://example.com/api/users/1/posts?limit=10
/api
:通常标识这是一个 API 接口。
/users
:表示操作的是 用户资源。
/1
:表示操作的是 ID=1 的用户。
/posts
:表示操作的是该用户的 帖子(子资源)。
?limit=10
:查询参数(可选),用于过滤、排序或分页。
2. RESTful API 路径的作用
(1) 标准化资源访问
-
每个 URL 代表一种 资源(如用户、订单、商品)。
-
使用 HTTP 方法(GET、POST、PUT、DELETE)来定义操作类型:
HTTP 方法 用途 示例(用户管理) GET
获取资源 GET /api/users
(获取所有用户)POST
创建资源 POST /api/users
(新增用户)PUT
更新整个资源 PUT /api/users/1
(更新用户1)PATCH
部分更新资源 PATCH /api/users/1
(修改用户1的部分字段)DELETE
删除资源 DELETE /api/users/1
(删除用户1)
(2) 可读性强
-
路径清晰,例如:
-
GET /api/orders/100
→ 获取订单 ID=100 的详情。 -
DELETE /api/products/5
→ 删除商品 ID=5。
-
(3) 无状态(Stateless)
-
每个请求包含所有必要信息,服务器不存储会话状态,适合分布式系统。
(4) 支持缓存、可扩展
-
由于使用 HTTP 标准,可以方便地利用 CDN 缓存、负载均衡 等技术。
3. 哪里会用到 RESTful API?
(1) 前后端分离开发
-
前端(Web/App)通过 RESTful API 与后端(服务器)交互,获取或提交数据。
-
例如:
-
Vue/React 前端:
fetch("/api/users")
获取用户列表。 -
移动端(Android/iOS):调用
GET /api/products
获取商品数据。
-
(2) 微服务架构
-
不同服务之间通过 RESTful API 通信,例如:
-
订单服务调用支付服务:
POST /api/payments
。 -
用户服务调用通知服务:
POST /api/notifications
。
-
(3) 第三方开放平台
-
许多公司提供 RESTful API 供开发者使用,例如:
-
Twitter API:
GET /2/tweets/{id}
获取推文。 -
GitHub API:
GET /repos/{owner}/{repo}
获取仓库信息。 -
Stripe 支付 API:
POST /v1/payment_intents
创建支付订单。
-
(4) 企业内部系统
-
企业内部不同系统(ERP、CRM)通过 RESTful API 交换数据。
4. RESTful API 路径设计最佳实践
(1) 资源命名使用名词(而非动词)
-
✅ 正确:
/api/users
(资源:用户) -
❌ 错误:
/api/getUsers
(违反 REST 风格)
(2) 使用复数形式
-
通常使用复数形式表示资源集合:
-
/api/users
(而不是/api/user
) -
/api/products
(而不是/api/product
)
-
(3) 层级关系表示子资源
-
例如:
-
GET /api/users/1/posts
→ 获取用户 1 的所有帖子。 -
POST /api/users/1/posts
→ 为用户 1 创建新帖子。
-
(4) 使用查询参数(?)进行过滤、分页
-
GET /api/orders?status=completed
→ 获取已完成的订单。 -
GET /api/products?page=2&limit=10
→ 分页获取商品。
(5) 版本控制(可选)
-
在 URL 或 Header 中加入版本号,例如:
-
GET /api/v1/users
-
GET /api/v2/users
-
5. 示例:一个完整的 RESTful API 设计
假设我们有一个 博客系统,API 设计如下:
功能 | HTTP 方法 | 路径 | 描述 |
---|---|---|---|
获取所有文章 | GET | /api/posts | 返回文章列表 |
创建新文章 | POST | /api/posts | 新增一篇文章 |
获取单篇文章 | GET | /api/posts/1 | 返回 ID=1 的文章 |
更新文章 | PUT | /api/posts/1 | 修改 ID=1 的文章 |
删除文章 | DELETE | /api/posts/1 | 删除 ID=1 的文章 |
获取文章的所有评论 | GET | /api/posts/1/comments | 获取文章 1 的评论 |
新增评论 | POST | /api/posts/1/comments | 给文章 1 添加评论 |
6. 总结
-
RESTful API 路径 是基于 HTTP 的标准化资源访问方式。
-
用途:前后端交互、微服务通信、开放平台 API。
-
核心特点:
-
使用 名词 表示资源(如
/users
)。 -
通过 HTTP 方法 定义操作(GET/POST/PUT/DELETE)。
-
路径清晰、可读性强、支持缓存和扩展。
-
-
最佳实践:使用复数名词、层级表示关系、查询参数过滤数据。
NahamCon CTF 2025-Fuzzies
题目描述:
对一个似乎是玩具公司的网站进行fuzzing模糊测试,总共有5个flag,这个题讲述的故事还有点细思极恐,有点意思
Flag1
由于题目给出了两个爆破字典,我们可以先试试目录遍历看看有没有什么数据泄露或者后台管理员登录界面等
使用工具dirsearch并使用命令python dirsearch.py -u "url" -w "字典路径" -e *
成功找到以上路径,其中upload和images都无法正常访问
这个admin界面应该就是管理员的登录界面
尝试sql注入无果,于是使用题目所给字典爆破
但失败了
应该是账号出错了,于是聪明的我注意到在memory界面有很多名字,结果我就把这些名字一个一个当成用户名去尝试了,结果浪费一大把时间。这里的关键点应该是api路径,利用方式也就是上面说的RESTful API路径
我们尝试访问/api/users,查看是否有用户信息,虽然没有访问到,但提示是401要求身份验证,那么也证明是有信息的,再随便访问一个别的,通过对比可以证明这一点
猜测后面路径跟上数字表示用户id,在输入数字时401报错,不是数字时出现endpoint not found报错,猜想确实是有用户id这一说并且就是使用数字表示id
既然知道了有大概有用户id这一说,那按照api的套路后面的路径就大概率还是功能模块,但我们不知道模块名字叫什么,于是继续使用他给出的字典爆破
发现存在一个功能模块叫log,并且回显的是user not found
那么应该是没有用户id为1的用户,那么再继续爆破用户id就好了
在用户id为87时发现有有用内容回显
访问api/users/87/log,发现第一个flag
Flag2
上面我们找到了第一个flag,其后面紧跟着一个username,叫做brian.1954,那么就尝试使用这个账号登录并且爆破这个账号的密码
在密码为dalls时返回数据长度不同并且状态码为302跳转,大概率就是密码
使用密码dallas登录,发现登录成功,以及第二个flag
Flag3
进入管理员界面后,我们先看Memory Management,从这里故事就有点细思极恐的感觉了
以及前面的memory里有说到一个人弄丢了fuzzy但是后面发现fuzzy自己坐在公园长椅上等她,当时就感觉这fuzzy不会有生命吧,或者说被恶灵附身了什么的,感觉有点意思,现在加上这两条未公开的回忆,更让人觉得这个玩具工厂没有那么简单了
说回正题,我尝试通过这两条未被接受的memory,并且抓包查看其中内容,但是似乎没有什么有效信息
于是将方向转向另一个模块Internal messages
这里有三篇文章,其中第三片文章说到产品问题,说到玩具绝对不能被淋湿,然而前面有一条memory就是他在洗澡时,玩具fuzzy掉入了水中,然后fuzzy不见了,最后他的房子都被毁了,可能是遇到水就会唤醒fuzzy心里沉睡的野兽?还是通过水这个生命源泉赋予了它生命?还是恶灵的召唤需要水元素???真实细思极恐啊,有点意思。
又扯远了
我们可以注意到这里访问每一个文章时url都有对应的类似文章id的部分
于是我就想试着使用爆破的方式看看有没有隐藏的文章
还真找到了两个,分别是id为98和842
其中98的是关于新工厂的地理位置
我勒个是在墓地上建造啊,这样恶灵附身的说法就更有可能了,当时做到这里真实冷汗直冒,但似乎这没有别的什么有用信息了,我们再看842
成功从842里找到了第3个flag
这篇文章表述这个工厂在研发一种活体毛绒玩具,又细思极恐了>_<
Flag4
前面给到了这个二维码的UUID,在开始时的界面Our collection里的界面源代码里有提到
这里的图片应该是从/api/fuzzies这个路径下获取的
我们试着访问这个路径
可以看到很多图片的信息包括名字和id等
那么我们可以根据RESTful API的格式来通过拼接参数来查询我们想要的内容
我们在后面跟上参数?id=666e8400-e29b-41d4-a716-446655440666来查看前面二维码的图片信息
这里发现第四个flag
Flag5
我们已经发现了这张隐藏的图片,那么就试着去看看这张图片,这里图片信息已经给出路径和名称了,为/images/fuzzies/the-evid-one.png(看到这名字时候感觉有点不对劲,难道终于要发现这个恶灵了吗)
我勒个去啊,当时做到这真给我吓一小跳,这跟前面画风差别太大了吧
看看着差别
最后一个flag就藏在那张鬼图里面,我们将the-evil-one.png下载后使用010 editor打开直接搜索flag,就找到最后一个flag了
或者使用exitfool工具查看也可以
总结
至此所有的flag都找到了,这里只要发现第一个flag后接下来的任务都不算太难,主要考了RESTful API的了解和利用,同时这个故事更是深得我心,在温暖温馨的画风中穿插了一条恐怖悬疑暗线,一个CTF题目设计成这样我觉得还是非常有意思的,在做的时候并不会感到累进而带替的是对了解故事真相的渴望