文章目录
- Ⅰ. URL
- Ⅱ. 报文格式
- Ⅲ. HTTP 请求方法
- 💥 `GET` 和 `POST` 的区别
- Ⅳ. HTTP 常见报头
- Ⅴ. HTTP 状态码
- Ⅵ. 会话保持
- 一、Cookie
- 二、Session
- 三、两者区别
- 四、理解 cookie、session、token 三者的区别
Ⅰ. URL
统一资源描述定位符URL(Uniform Resource Locator)是用来表示从互联网上得到的资源位置和访问这些资源的方法,说的简单直白一点,就是我们平时在访问页面时候输入的网址!
为什么要有这个URL呢❓❓❓
其实和HTTP协议的出现是差不多的情况,就是因为我们需要去统一怎么标志分布在整个互联网上的万维网文档,所以必须要有一个统一的格式去描述这些文档,那么万维网使用的就是URL来解决,并且它在整个互联网范围内是唯一的!
一个URL大致由如下几部分构成:
💥注意事项:
- 查询字符串以
?开头,字符串内容以键值对形式出现,多个字符串之间用&进行分割。- 查询字符串是由程序员自定义的。
- 片段标识符是前端开发负责的,可以理解为一个前端的跳转链接。例如 Vue官方文档,通过不同的片段标识跳转到文档的不同章节。
URL当中除了会对这些特殊符号做编码,对中文也会进行编码,第一是为了压缩文本,减少网络资源消耗;第二是为了保证中文不会出现乱码的情况,避免出现某些浏览器等解析URL失败导致跳转失败,带来损失!- 在报文的正文中既可以存文本数据,也可以存二进制数据,但是查询字符串只能存放文本数据。为了能够在查询字符串中存放二进制数据,可以先将二进制数据,通过常用的
base64编码转变成文本数据,然后再存放到查询字符串,相当于间接存放二进制数据,解析时候再通过base64解码得到原本的二进制数据!
Ⅱ. 报文格式
💥注意事项:
- 在一行中用空格隔开不同内容,而行与行之间用
CRLF来隔开。 HTTP在报头中引入了Content-Type和Content-Length来解决TCP的粘包问题:- 读取报文的时候,如果报头中不存在上述两个字段,说明没有正文,则读到一个空行
CRLF之后就结束。 - 读取报文的时候,如果报头中存在上述两个字段,则浏览器会按照
Content-Length来读取对应大小的请求正文内容,然后按照Content-Type选择对应的资源处理方式来处理信息! - 如果报头中只出现了两个字段中的其中之一,则很有可能是违法的报文,通常浏览器会自动拦截!
- 读取报文的时候,如果报头中不存在上述两个字段,说明没有正文,则读到一个空行
Ⅲ. HTTP 请求方法
| 方法 | 说明 | 支持的HTTP协议版本 |
|---|---|---|
| GET | 获取资源 | 1.0、1.1 |
| POST | 上传资源(不限于文件) | 1.0、1.1 |
| PUT | 上传文件 | 1.0、1.1 |
| DELETE | 删除文件 | 1.0、1.1 |
| HEAD | 获取报文首部 | 1.0、1.1 |
| OPTIONS | 询问支持的方法 | 1.1 |
| TRACE | 用来进行环回测试的请求报文 | 1.1 |
| CONNECT | 要求用隧道协议连接代理,用于代理服务器 | 1.1 |
| LINK | 建立和资源之间的联系 | 1.0 |
💥注意事项:
- 前后端开发中,建议遵循
Restful风格,读用GET、写用POST、更新用PUT、删除用DELETE。 GET请求的URL的长度并没有任何限制,这取决于浏览器的实现和HTTP服务器端的实现。GET请求的触发时机:- 用户访问页面
- 点击超链接
- 提交带
method="get"的表单 - 前端通过
AJAX发送请求 - 浏览器自动请求静态资源(比如加载 CSS、JS、图片等资源时自动发起 GET 请求)
POST请求的触发时机:- 提交带
method="post"的表单(比如注册、登录) - 前端通过
AJAX发送POST请求 - 调用第三方接口或后端接口需要上传数据(比如上传图片、提交 JSON 或表单数据等)
- 提交带
💥GET和POST的区别
两者并没有本质区别,因为GET完全可以用于提交数据,POST也完全可以用于获取数据,只不过在使用习惯和特点有些区别,如下所示:
GET通常没有body,通过查询字符串传递数据给服务器;而POST通常有body,不需要通过查询字符串传递数据。- 语义上两者含义不同,
GET表示 “获取”;POST表示 “提交”。 GET通常要求幂等,故可以被缓存;POST一般是不幂等的,故不能被缓存。- 幂等:表示多次请求得到的结果是一致的
Ⅳ. HTTP 常见报头
| 类别 | 报头字段 | 说明 | 示例/常见值 |
|---|---|---|---|
| 通用报头 | Cache-Control | 控制缓存行为 | no-cache(不缓存) , max-age=3600(一小时) |
Connection | 控制是否为持久连接或设置特定连接选项 | keep-alive(长连接) , close(不长连接) | |
Date | 消息发送时间 | Mon, 18 May 2025 08:30:00 GMT | |
| 请求报头 | Host | 指定服务器的主机名和端口号(HTTP/1.1 必需) | example.com:80 |
User-Agent | 浏览器或客户端的信息(历史遗留问题) | Mozilla/5.0 … | |
Accept | 客户端可接收的响应内容类型 | text/html, application/json | |
Accept-Language | 客户端可接收的语言 | zh-CN, en-US;q=0.8 | |
Accept-Encoding | 客户端支持的压缩编码方式 | gzip, deflate, br | |
Referer | 当前页面是哪个页面跳转过来的 | https://example.com/page.html | |
Authorization | 认证信息(如 Basic 或 Bearer Token) | Bearer eyJhbGci… | |
Cookie | 客户端发送给服务器的 Cookie 数据 | SESSIONID=abc123; lang=zh | |
| 响应报头 | Server | 提供服务的 Web 服务器软件信息 | nginx/1.21.6 |
Set-Cookie | 服务器设置的 Cookie | SESSIONID=xyz456; Path=/; | |
Location | 重定向目标 URL(用于 3xx 状态码) | https://example.com/login | |
WWW-Authenticate | 认证请求头(如需登录提示) | Basic realm=“Access to site” | |
Content-Type | 响应内容的类型 | application/json, text/html | |
Content-Length | 响应体的字节长度 | 1234 | |
Content-Encoding | 响应体的压缩编码方式 | gzip, br | |
| 缓存相关 | ETag | 响应资源的唯一标识符,支持缓存对比 | “abc123etag” |
Last-Modified | 响应资源的最后修改时间 | Tue, 18 Apr 2025 06:20:00 GMT | |
Expires | 指定资源过期时间(通常和Cache-Control配合使用) | Wed, 19 May 2025 08:30:00 GMT |
Ⅴ. HTTP 状态码
| 状态码 | 说明 |
|---|---|
| 100 Continue | 继续请求,客户端应继续发送剩余部分 |
| 101 Switching Protocols | 切换协议,服务器同意更换通信协议 |
| 102 Processing | 正在处理请求(WebDAV 扩展) |
| 200 OK | 请求成功 |
| 201 Created | 请求成功并创建了新资源 |
| 202 Accepted | 请求已接受,尚未处理 |
| 204 No Content | 请求成功但无返回内容 |
| 206 Partial Content | 部分内容响应(断点续传) |
| 301 Moved Permanently | 资源已永久移动 |
| 302 Found | 临时重定向(原称Moved Temporarily) |
| 303 See Other | 重定向使用GET获取其他URI |
| 304 Not Modified | 资源未修改,可使用缓存 |
| 307 Temporary Redirect | 临时重定向,使用原请求方法 |
| 308 Permanent Redirect | 永久重定向,使用原请求方法 |
| 400 Bad Request | 请求格式错误,服务器无法理解 |
| 401 Unauthorized | 未授权,需身份验证 |
| 403 Forbidden | 拒绝访问,权限不足 |
| 404 Not Found | 请求资源不存在 |
| 405 Method Not Allowed | 请求方法不允许(比如服务器不一定支持GET等方法) |
| 408 Request Timeout | 请求超时 |
| 409 Conflict | 请求冲突(如版本冲突) |
| 413 Payload Too Large | 请求体太大 |
| 429 Too Many Requests | 请求过多,被限流 |
| 500 Internal Server Error | 服务器内部错误 |
| 501 Not Implemented | 服务器不支持该请求方法 |
| 502 Bad Gateway | 网关收到无效响应 |
| 503 Service Unavailable | 服务不可用(服务器过载或维护中) |
| 504 Gateway Timeout | 网关响应超时 |
| 505 HTTP Version Not Supported | HTTP版本不受支持 |
💥重定向注意细节:
- 静态资源、页面重定向可用
301(永久)或302(临时),但要清楚方法可能变化(即可能从POST变成GET,导致方法体丢失等情况) - 表单、REST API 等需要保持方法的请求,应优先使用
307(临时)或308(永久),方法不会变化 - 重定向的地址可以从响应报文中的
Location字段获取!
Ⅵ. 会话保持
一、Cookie
要实现会话保持还是挺复杂的,但是Cookie技术就不一样了,它只是做到让人看起来就像是会话一直保持着一样,但实际还是原来的无状态通信,只是稍微做了一下修改:多携带一些状态信息!
cookie信息是在服务端创建的,但最后保存在客户端。在cookie有效期内,后续的浏览器的请求就会带上对应的cookie信息,服务端收到请求后,识别cookie就可以知道当前发起请求的用户是哪一个,而且浏览器下次再次需要相同信息时,比如用户名什么的,可以直接从cookie里获取,而不用再次让用户发起请求获取。
我们可以通过在服务器的响应中设置cookie字段,这个字段名我们之前介绍过,叫做Set-Cookie,其后面跟的就是给用户提供的鉴权信息,并且可以设置该cookie的最大生存时间,当过了该时间之后,在客户端会进行时间的对比,超时了cookie就失效了,就要重新在请求中带上账号密码等信息,对应到用户就是要重新输入密码进行登录了!
// 往后20秒,每次http请求时候都会自动携带曾经设置的所有cookie,帮助服务器进行鉴权行为 resphead += "Set-Cookie: name=lirendada; Max-Age=20\r\n";二、Session
为了提高安全性,于是引入了session机制,其实就是将原来保存在客户端的cookie,现在变成了由服务端来保存管理,如下图所示:
流程如下所示:
- 用户第一次登录,后端创建一个
Session(服务器端); - 后端生成一个
Session ID,通过Set-Cookie响应头发送给客户端; - 客户端浏览器将
Session ID保存在Cookie中; - 后续每次请求浏览器都会自动带上该
Cookie,服务器通过Session ID找到用户的Session数据。
三、两者区别
| Cookie | Session | |
|---|---|---|
| 存储位置 | 客户端(浏览器) | 服务器端 |
| 存储内容 | 一般为少量数据,如用户标识等 | 一般为用户的完整会话数据 |
| 安全性 | 相对较低,容易被窃取或篡改 | 相对较高,不暴露给客户端 |
| 生命周期 | 可设置过期时间 | 浏览器关闭或超时失效(可配置) |
| 占用资源 | 占客户端资源 | 占服务器资源 |
| 传输方式 | 每次请求自动携带到服务器 | 通过 session ID 与请求关联 |
| 使用场景 | 记住登录信息、用户偏好 | 用户登录状态、购物车、权限管理等 |
四、理解 cookie、session、token 三者的区别
- cookie 存放在客户端,可以存放任何数据,但是容易泄漏,所以通常存放的是 sessionid,而不是直接存放用户信息。
- session 存放在服务端,一般存放用户信息(用于认证),然后据此生成 sessionid 发送给客户端,以后每次客户端访问服务器都会在 cookie 中带上该 sessionid,方便服务端验证。
- 但是 session 存在这些问题:
- 占用服务器资源
- 在分布式集群中存在一致性问题
- 依赖 cookie,所以存在跨域问题
- sessionid 一旦泄漏,攻击者就能伪造身份进行登录,存在安全隐患
- 但是 session 存在这些问题:
- token 通常存放在客户端,是一种代表用户身份或会话的字符串凭证,本质上就是 “访问票据”。
- token 应用时候有两种类型:
- 随机字符串 token
- 后端生成随机 ID,存到 Redis 对应用户信息
- 前端请求带 token,服务器查 Redis 获取用户数据
- 优势:服务器可随时失效 token
- JWT(JSON Web Token)
- 自包含 token,把用户信息和过期时间写进 token 本身,并用签名保护
- 不需要每次查 Redis,即可验证身份
- 缺点:一旦签发,服务器无法轻易强制失效(除非加黑名单)
- 随机字符串 token
- token 应用时候有两种类型: