目录
[1. RESTful 规范的偏差](#1. RESTful 规范的偏差)
[1.1 RESTful 接口规范](#1.1 RESTful 接口规范)
[1.2.1 定义](#1.2.1 定义)
[1.2.2. 最直观例子(一看就懂)](#1.2.2. 最直观例子(一看就懂))
[1.2.3. 包含关系(最关键)](#1.2.3. 包含关系(最关键))
[1.3 RESTful无状态:](#1.3 RESTful无状态:)
[1.4.8极简总结(面试 30 秒收尾)](#1.4.8极简总结(面试 30 秒收尾))
[1、PUT 与 POST](#1、PUT 与 POST)
[1.2 PUT 与 POST 的核心区别(幂等性视角)](#1.2 PUT 与 POST 的核心区别(幂等性视角))
[2. 早期跨域JSONP](#2. 早期跨域JSONP)
[2.2 JSONP 跨域方案](#2.2 JSONP 跨域方案)
一、RESTful
1. RESTful 规范的偏差
- 错误 1:「URL如果需要分开,必须用 - 隔离」→ 精准表述:URI 中多单词的资源名 用
-分隔(如/user-addresses),而非「URL」;且这是「最佳实践」而非「强制规则」,核心是统一风格,避免驼峰 / 下划线。- 错误 2:「请求方法中的名称必须是小写」→ 精准表述:URI 路径统一小写(HTTP 方法本身就是大写 / 小写不敏感,如 GET/Post 都可,但 URI 是区分大小写的,因此统一小写)。
- 遗漏:RESTful 核心是「HTTP 方法映射资源操作」(GET 查 / POST 增 / PUT 全量更 / PATCH 部分更 / DELETE 删)、「无状态」「可缓存」,这是比命名规范更核心的原则。
1.1 RESTful 接口规范
RESTful 是「以资源为中心」的接口设计风格(非强制标准),核心适配前后端分离、微服务等场景,关键规则:
- 核心原则:接口围绕「资源(名词)」设计,而非「动作(动词)」;HTTP 方法表达操作意图(GET 查 / POST 增 / PUT 全量更 / PATCH 部分更 / DELETE 删);接口无状态(每次请求包含所有必要信息)、可缓存。
- 命名规范:URI 用小写,多单词资源名用
-分隔(如/user-addresses);资源集合用复数(如/users);URI 层级不超过 2-3 层(如/users/123/orders)。 - 适用场景:适用于大部分数据交互场景,不适用于实时通信(如聊天、推送,优先用 WebSocket)。
1.2URL和URI的关系及区别:
重点:URL ⊂ URI
1.2.1 定义
- URI:能唯一标识一个资源的字符串只要能 "认出这个资源",就是 URI。
- URL:不仅能标识资源,还能 定位资源(告诉你怎么访问) 必须带协议、地址、路径,能直接访问。
- URI = 唯一标识资源(名字)
- URL = 唯一标识 + 定位资源(名字 + 地址)
- URL 是 URI 的子集
1.2.2. 最直观例子(一看就懂)
这是 URI(只标识资源):
javascript
/users/123
它只告诉你这是哪个资源 ,但不知道怎么访问。
这是 URL(能定位资源):
javascript
https://api.xxx.com/users/123
它既标识资源,又告诉你怎么访问。
1.2.3. 包含关系(最关键)
javascript
URI 最大
├── URL(通过位置定位资源:带协议、域名)
└── URN(通过名字标识资源:如 urn:isbn:978xxx)
所以:👉 URL ⊂ URI, 👉 URI=URL+URN
1.3 RESTful无状态:
-
RESTful 「无状态」的核心:服务端不存储客户端会话状态,每个请求必须携带处理所需的全部信息,请求独立、无上下文依赖;
-
核心价值:服务端易扩展、容错性高、接口可测试 / 可缓存;
-
落地关键:用 Token/JWT 替代 Session 传递认证信息,请求参数明确、自包含,避免依赖服务端会话状态。
1.3.1落地示例:
javascript
// 客户端请求(无状态:携带完整认证信息和参数)
axios.get('https://api.example.com/v1/orders', {
headers: {
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', // 包含用户ID、角色
'Content-Type': 'application/json'
},
params: {
userId: 123, // 明确指定查询的用户ID(无需服务端从会话中取)
status: 'paid',
page: 1,
size: 10
}
});
// 服务端处理逻辑(无状态)
function handleOrderRequest(req) {
// 1. 解析请求头中的JWT,获取用户ID和角色(无需查会话)
const { userId: tokenUserId, role } = verifyJWT(req.headers.Authorization);
// 2. 校验请求参数中的userId与token中的一致(防止越权)
if (tokenUserId !== req.params.userId) return 403;
// 3. 仅根据请求参数查询数据,无任何会话状态依赖
const orders = queryOrders(req.params);
// 4. 返回结果,不存储任何与该请求相关的状态
return { code: 0, data: orders };
}
分析:
- 客户端:
GET /users→ 请求头携带Authorization: Bearer <JWT令牌>(包含用户 ID、角色等信息),查询参数page=1&size=10;- 服务端:仅通过「JWT 令牌 + 查询参数」验证身份、判断权限、查询数据,处理完成后直接返回结果,不记录「该用户刚查过用户列表」「该用户已登录」等状态;
- 优势:即使服务端重启 / 多台服务器负载均衡,只要请求携带完整信息,就能正常处理。
1.3.2"无状态"的核心特征(面试必答)
-
请求自包含 :每个请求必须携带「认证信息(Token/JWT)、业务参数、权限相关数据」等所有必要信息,服务端无需从「会话」中补充任何上下文。
- 有状态:请求仅携带
sessionId,服务端通过sessionId查会话状态获取用户信息; - 无状态:请求携带
JWT 令牌(包含用户 ID、角色),服务端解析令牌即可获取所有用户信息。
- 有状态:请求仅携带
-
服务端无会话存储:服务端不存储任何与客户端相关的临时状态(如登录状态、操作记录、分页上下文),所有状态要么在客户端存储(如 Token、本地缓存),要么在请求中传递。
-
请求独立无关:每个请求的处理结果仅依赖自身携带的信息,与之前 / 之后的请求无关联 ------ 即使客户端连续发送 10 个请求,服务端也不会将这些请求视为「同一个会话的操作」,每个请求都是独立的。
1.3.3"无状态"的设计价值(面试加分)
-
服务端易扩展:无状态意味着多台服务器可无差别处理请求(负载均衡),无需同步会话状态 ------ 比如用户第一次请求到服务器 A,第二次请求到服务器 B,只要请求携带完整信息,B 就能正常处理,这是微服务、分布式系统的核心基础。
-
容错性更高:服务端重启、宕机不会影响请求处理(只要请求信息完整),因为服务端没有需要持久化的会话状态,恢复后即可处理新请求。
-
接口更简洁、可测试:每个请求都是独立的,测试时无需模拟「先登录→再查询」的会话流程,直接发送携带 Token 的请求即可验证接口功能,降低测试复杂度。
-
可缓存性提升 :无状态的 GET 请求(如
/products/123)不依赖会话状态,只要参数相同,响应结果就是一致的,客户端 / 网关可直接缓存,提升性能。
1.3.4常见误区(面试避坑)
-
误区 1:「无状态 = 服务端不存储任何数据」→ 错误!服务端仍会存储「资源数据」(如用户信息、订单数据),只是不存储「客户端会话状态」(如登录状态、操作上下文)。
-
误区 2:「无状态 = 客户端不能存储状态」→ 错误!客户端可存储状态(如 Token、分页页码、筛选条件),只是这些状态无需同步到服务端,仅在请求时携带即可。
-
误区 3:「无状态 = 接口不能有业务状态」→ 错误!接口可返回「资源的业务状态」(如订单状态
status=paid),但服务端不会记录「客户端已查询过该订单状态」这类会话状态。
1.4如何确保RESTful接口的安全性:
RESTful 接口安全围绕无状态、统一接口 设计,从身份、权限、传输、请求、攻击、日志六层做防护:
1.4.1身份认证(你是谁)
REST 无状态,不用 Session/Cookie ,只用令牌认证:
- JWT 登录后生成加密令牌,请求放在
Authorization: Bearer token里;用 RSA 非对称加密,设置短过期时间 + 刷新令牌,Payload 不存敏感信息。 - OAuth2.0用于第三方开放平台,通过授权码访问,严格控制权限范围(Scope)。
- API Key + Secret服务间调用,用密钥 + 时间戳签名,防止明文泄露。
1.4.2权限控制(你能做什么)
认证通过后,防止越权:
- RBAC 角色权限给角色分配权限,用户关联角色,普通用户 / 管理员分开控制。
- **ABAC 属性权限(进阶)**按用户、资源、环境动态判断,适合复杂权限场景。
- 资源归属校验必须校验:只能操作自己的订单 / 数据,防止水平 / 垂直越权。
1.4.3传输安全(数据不被偷改)
- 强制 HTTPS全程 TLS 加密,禁用低版本协议,开启 HSTS 强制 HTTPS。
- 敏感数据二次加密手机号、身份证、支付信息用 AES 再加密,不裸传。
1.4.4请求合法性校验(过滤恶意请求)
- 全参数校验校验格式、范围、防 SQL/XSS 注入,非法直接返回 400。
- 接口限流按 IP / 用户 ID 限制频率,防刷接口,超限返回 429。
- 防 CSRF校验 Origin/Referer,非 GET 请求携带 CSRF Token。
1.4.5防常见攻击(兜底安全)
- 防 SQL 注入使用参数化查询 / ORM,不直接拼接 SQL。
- 防 XSS返回内容转义特殊字符,不执行用户输入的脚本。
- 防重放攻击时间戳 + 随机数 + 签名,关键接口保证只执行一次。
1.4.6审计与追溯(出问题可查)
- 全量日志记录用户、IP、接口、参数、状态,敏感操作留快照。
- 日志脱敏密码、证件号显示为 ****。
- 异常监控告警实时发现暴力破解、异常访问。
1.4.7额外注意
- 不在 URL 里放敏感信息;
- 接口做版本控制,方便安全升级;
- 登录接口做弱口令检测、异常锁定。
1.4.8极简总结(面试 30 秒收尾)
RESTful 接口安全采用六层防护 :身份认证(JWT/OAuth)→ 权限控制(RBAC / 资源校验)→ 传输加密(HTTPS)→ 请求校验(参数 / 限流)→ 攻击防护(注入 / 重放)→ 审计日志。
核心原则:最小权限、数据最小化、全程加密,在保证安全的同时兼顾性能与扩展性。
二、HTTP相关知识
1、PUT 与 POST
1.1PUT与POST的偏差:
- 错误 1:「post 创建资源会创建不同的 URI」→ 精准表述:POST 是「向资源集合(如
/users)创建新资源,服务端自动生成资源 ID,新资源的 URI 是集合 + ID(如/users/123)」,而非 POST 直接创建不同 URI;- 错误 2:「put 不适用于新增资源」→ 精准表述:PUT 「不适合普通新增场景」(服务端分配 ID),但可用于「客户端指定 ID 的新增 / 替换」(如
PUT /users/456,不存在则创建,存在则替换),核心是「幂等性」而非「完全不能新增」。
1.2 PUT 与 POST 的核心区别(幂等性视角)
- PUT:幂等性方法,核心语义是「替换 / 创建指定 URI 的资源」(如
PUT /users/123);- 用于「全量更新已有资源」(多次调用结果一致);
- 特殊场景可用于「客户端指定 ID 的资源创建」(不存在则创建,存在则替换);
- 不适合「服务端分配 ID 的普通新增场景」(如创建订单 / 用户),因为多次调用只会操作同一个 URI,无法生成多个新资源。
- POST:非幂等性方法,核心语义是「向资源集合创建新资源」(如
POST /users);- 服务端自动生成资源 ID,新资源 URI 为「集合 + ID」(如
/users/123); - 多次调用会创建多个独立资源,是「普通新增场景」的标准选择。
- 服务端自动生成资源 ID,新资源 URI 为「集合 + ID」(如
2. 早期跨域JSONP
2.1JSONP的偏差:
- 错误 1:「URI 的参数有限,应该只有 50 多个」→ 精准表述:URL 长度限制不是「50 多个字符」,而是不同浏览器 / 服务器有不同限制(如 IE 最大 2083 字符、Nginx 默认 4k 左右),核心是「GET 参数拼接在 URL 中,长度有限,无法传输大量数据」;
- 错误 2:「容易暴露数据信息」→ 精准表述:JSONP 的核心安全风险是「执行服务端返回的 JS 代码,易引发 XSS 攻击」,而「数据暴露」是 GET 请求的问题(URL 中的参数易被抓包 / 历史记录捕获),需区分两类风险。
2.2 JSONP 跨域方案
JSONP 是早期解决跨域的临时方案,核心利用 <script> 标签不受同源策略限制的特性,实现逻辑:
- 实现步骤:创建
<script>标签 → 定义全局回调函数 → 设置src为跨域地址(带callback=回调函数名参数)→ 插入 DOM 触发请求 → 服务端返回「回调函数 (数据)」格式的 JS 代码 → 浏览器执行代码触发回调,接收数据。 - 核心缺点:① 仅支持 GET 请求(
<script>标签的src天然发起 GET 请求);② 传输数据量有限(GET 参数拼接在 URL 中,受 URL 长度限制,如 IE 最大 2083 字符);③ 安全风险高:需执行服务端返回的 JS 代码,易引发 XSS 攻击;GET 参数易被抓包 / 历史记录捕获,敏感数据易泄露;④ 无原生错误处理(无法感知请求超时 / 失败),工程化维护成本高。
三、上述总结(部分)
- RESTful 核心是「资源为中心 + HTTP 方法语义 + 无状态」,命名规范是落地细节,而非核心;
- PUT 与 POST 的核心差异是「幂等性」:PUT 多次调用结果一致,适合更新 / 客户端指定 ID 的创建;POST 多次调用创建多资源,适合普通新增;
- JSONP 缺点本质源于
<script>标签特性:仅支持 GET、数据量有限、安全风险高,现代场景优先用 CORS 替代。
晚安啦煲仔们,周末愉快啦~😀