本篇概览:
OSI 七层模型是什么?每一层的作用是什么?TCP/IP四层模型和OSI七层模型的区别是什么?
HTTP 本身是无状态协议,HTTP如何保存用户状态?
能不能具体说一下Cookie的工作原理、生命周期、作用域?使用Cookie存储会话信息会有什么局限?
Session和Cookie的区别是什么?如果没有 Cookie 的话 Session 还能用吗?多服务器节点下 Session-Cookie 方案如何做?
OSI 七层模型是什么?每一层的作用是什么?TCP/IP四层模型和OSI七层模型的区别是什么?
OSI(开放系统互联)七层模型是一种用于理解和实现网络通信的分层模型,它将网络通信过程划分为七个独立的功能层。每一层专注于完成特定的任务,并为上一层提供服务,同时依赖下一层的支持。以下是OSI七层模型的详细描述及其每一层的作用:
应用层(Application Layer)
- 作用
应用层是OSI模型的最高层,直接与用户交互,提供网络服务和应用程序接口。
- 关键功能
-
- 提供用户访问网络资源的接口。
- 支持文件传输、电子邮件、远程登录等功能。
- 典型协议
-
- HTTP(超文本传输协议)、FTP(文件传输协议)、SMTP(简单邮件传输协议)、DNS(域名系统)。
表示层(Presentation Layer)
- 作用
表示层负责数据格式的转换、加密和压缩,以确保数据能够在不同系统之间正确解释。
- 关键功能
-
- 数据编码和解码(如ASCII、EBCDIC)。
- 数据加密和解密(如SSL/TLS)。
- 数据压缩和解压缩。
- 典型协议
-
- SSL/TLS。
会话层(Session Layer)
- 作用会话层负责建立、管理和终止应用程序之间的会话(通信会话)。
- 关键功能
-
- 控制会话的建立、维护和断开。
- 提供会话同步和检查点功能(如断点续传)。
- 典型协议
-
- NetBIOS、RPC(远程过程调用)、PPTP(点对点隧道协议)。
传输层(Transport Layer)
- 作用
传输层负责端到端的通信,确保数据完整、有序地从源主机传输到目标主机。
- 关键功能
-
- 提供可靠的数据传输(如TCP)或不可靠的数据传输(如UDP)。
- 实现流量控制和错误恢复。
- 数据分段和重组。
- 典型协议
-
- TCP(传输控制协议):面向连接,可靠传输。
- UDP(用户数据报协议):无连接,快速但不可靠。
网络层(Network Layer)
- 作用
网络层负责数据包的路由选择和转发,确保数据能够从源主机到达目标主机。
- 关键功能
-
- 提供逻辑地址(如IP地址)。
- 路由选择和数据包转发。
- 分段和重组数据包。
- 典型协议/设备
-
- 设备:路由器。
- 协议:IP(IPv4/IPv6)、ICMP、ARP。
数据链路层(Data Link Layer)
- 作用
数据链路层负责在相邻节点之间可靠地传输数据帧,并处理物理层可能引入的错误(如比特错误)。
- 关键功能
-
- 将比特流封装成帧。
- 实现流量控制和错误检测与纠正。
- 定义MAC地址(媒体访问控制地址)以标识设备。
- 典型协议/设备
-
- 设备:交换机、网桥。
- 协议:以太网(Ethernet)、PPP(点对点协议)、HDLC。
物理层(Physical Layer)
- 作用
物理层负责在物理介质上传输原始的比特流(0和1)。它定义了硬件设备(如网卡、电缆等)之间的电气、机械、功能和规程特性。
- 关键功能
-
- 定义电压、接口、电缆标准等。
- 实现比特流的传输和接收。
- 提供物理连接的建立、维护和释放。
- 典型协议/设备
-
- 设备:中继器、集线器
OSI七层模型通过分层的方式,将复杂的网络通信任务分解为多个独立的功能模块。每一层都专注于完成特定的任务,并为上一层提供支持。这种分层设计使得不同的网络协议和设备可以协同工作,从而实现跨网络的通信。
- 高三层(应用层、表示层、会话层)
更接近用户,负责提供高级的网络服务和数据处理功能。
- 低三层(传输层、网络层、数据链路层、物理层)
主要负责网络通信的基础部分,包括数据的传输、路由和链路管理。
TCP/IP四层模型:
从下到上分为四层:
- 网络接口层
对应OSI的物理层和数据链路层,负责硬件相关的数据传输。
- 网络层
对应OSI的网络层,负责数据包的路由和转发(如IP协议)。
- 传输层
对应OSI的传输层,提供端到端的通信(如TCP、UDP协议)。
- 应用层
整合了OSI的应用层、表示层和会话层功能,直接面向用户(如HTTP、DNS)。
对比维度 | OSI七层模型 | TCP/IP四层模型 |
---|---|---|
来源与理念 | 理论化,先有模型后有协议 |
实用化,先有协议后有模型 |
层次划分 | 七层(物理层到应用层) |
四层(网络接口层到应用层) |
功能整合 | 细粒度划分,功能独立 |
高三层合并为应用层,功能集成 |
实际应用 | 教学与理论研究为主 |
互联网通信的基础,广泛使用 |
协议支持 | 无具体协议绑定 |
明确绑定具体协议(如TCP、IP) |
数据封装 | 每层独立封装,过程较繁琐 |
封装过程简洁,效率更高 |
OSI七层模型更适合用于学习和理解网络通信的基本原理,而TCP/IP四层模型则因其高效性和实用性,成为现代网络通信的实际标准。
面试官:HTTP 本身是无状态协议,HTTP如何保存用户状态?
HTTP 是一种无状态(stateless)协议,这意味着每个请求和响应之间是相互独立的,服务器不会自动保存用户的会话状态。然而,在实际应用中,为了实现用户状态的保存(如登录状态、购物车信息等),通常采用以下几种机制:
1. 使用 Cookie
- 原理
服务器通过在 HTTP 响应头中设置
Set-Cookie
字段,将用户的状态信息存储到客户端。客户端在后续请求中会自动携带该 Cookie,从而实现状态的传递。 - 示例
-
服务器返回响应时设置
Set-Cookie: sessionId=abc123; Path=/; HttpOnly
。
客户端在下次请求时会在请求头中添加
Cookie: sessionId=abc123
。
- 优点
-
- 简单易用,适合保存少量数据。
- 支持过期时间、域名限制等安全特性。
- 缺点
-
- 数据存储在客户端,可能被篡改或窃取(需配合加密或签名使用)。
2. 使用 Session
- 原理
服务器为每个用户生成一个唯一的会话标识符(Session ID),并通过 Cookie 或 URL 重写的方式发送给客户端。实际的用户状态信息(如登录信息)存储在服务器端,客户端仅保存 Session ID。
- 示例
-
用户登录后,服务器生成一个 Session 并返回
Set-Cookie: sessionId=xyz456
。
客户端在后续请求中携带
Cookie: sessionId=xyz456
,服务器根据 ID 检索对应的用户状态。
- 优点
-
- 敏感数据存储在服务器端,安全性较高。
- 减少客户端的数据存储负担。
- 缺点
-
- 服务器需要维护大量会话数据,可能导致性能瓶颈。
3. 使用 Token(如 JWT)
- 原理
服务器在用户登录成功后生成一个令牌(Token),并将 Token 返回给客户端。客户端在后续请求中通过请求头(如
Authorization: Bearer
)携带该 Token。服务器通过验证 Token 的合法性来识别用户状态。 - JWT 示例
-
Token 格式:
Header.Payload.Signature
,其中 Payload 包含用户信息(如用户 ID、角色等)。
客户端发送请求时携带
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…
。
- 优点
-
- 无需服务器存储会话信息,支持分布式部署。
- Token 可包含自定义数据,减少数据库查询。
- 缺点
-
- Token 较大,增加了每次请求的开销。
- Token 一旦签发,无法轻易撤销(需引入黑名单机制)。
4. URL 重写
- 原理
将用户状态信息(如会话 ID)附加到 URL 中,作为请求的一部分传递给服务器。
- 示例
-
服务器返回的 URL:
http://example.com/cart?sessionId=12345
。
- 客户端点击链接时,会话 ID 随 URL 发送到服务器。
- 优点
-
- 不依赖 Cookie,适用于禁用 Cookie 的场景。
- 缺点
-
- URL 中暴露状态信息,存在安全隐患。
- URL 长度有限制,不适合存储复杂数据。
5. 隐藏表单字段
- 原理
在 HTML 表单中嵌入隐藏字段,用于存储用户状态信息。当用户提交表单时,这些信息会随请求一起发送到服务器。
- 示例
<input type="hidden" name="sessionId" value="abc123">
- 优点
-
- 简单易实现,适合特定场景。
- 缺点
-
- 仅适用于 POST 请求,无法覆盖所有交互场景。
- 安全性较低,容易被篡改。
总结
方法 | 存储位置 | 优点 | 缺点 |
---|---|---|---|
Cookie | 客户端 |
简单易用,支持过期时间 |
数据可能被篡改,存储容量有限 |
Session | 服务器端 |
安全性高,敏感数据不暴露 |
服务器存储压力大 |
Token(JWT) | 客户端 |
支持分布式,无需服务器存储 |
Token 较大,难以撤销 |
URL 重写 | URL 中 |
不依赖 Cookie |
存在安全隐患,URL 长度有限 |
隐藏表单字段 | HTML 表单中 |
实现简单 |
仅适用于特定场景,安全性低 |
综上所述,HTTP 协议虽然本身是无状态的,但通过上述机制(如 Cookie、Session、Token 等)可以有效地保存用户状态,满足不同场景的需求。
面试官:能不能具体说一下Cookie的工作原理、生命周期、作用域?使用Cookie存储会话信息会有什么局限?
Cookie是浏览器和服务器之间用于存储用户会话信息的小型文本文件Cookie的工作原理涉及多个环节,包括创建、存储、发送、更新以及安全措施等。以下是Cookie工作原理的详细介绍:
1. Cookie的创建与设置
当用户首次访问一个网站时,服务器可以通过HTTP响应头中的Set-Cookie
指令来创建一个Cookie。这个指令包含了Cookie的名称、值以及一些可选的属性。
例如:
Set-Cookie: sessionId=abc123; Path=/; HttpOnly; Secure; Max-Age=3600
- 键值对
sessionId=abc123
表示Cookie的名称是sessionId
,值是abc123
。 - 作用域
Path=/
表示这个Cookie在整个网站的所有路径下都有效。 - 安全性
-
HttpOnly
禁止JavaScript访问这个Cookie,有助于防止跨站脚本攻击(XSS)。
Secure
表示这个Cookie只能通过HTTPS协议传输,有助于防止中间人攻击。
- 生命周期
Max-Age=3600
表示这个Cookie在3600秒(1小时)后过期。
2. Cookie的存储与管理
浏览器会根据域名和路径规则来存储Cookie。每个域名下的Cookie都是独立存储的,例如,example.com
的Cookie和other.com
的Cookie是分开存储的。Cookie的作用域由Path
属性决定,例如,Path=/shop
的Cookie只在/shop
路径下有效。
浏览器还会根据Cookie的过期时间(Max-Age
或Expires
属性)来管理Cookie的生命周期。如果Cookie没有设置过期时间,它就是一个会话Cookie,会在浏览器关闭后自动删除。如果设置了过期时间,它就是一个持久性Cookie,会在指定的时间后过期。
3. Cookie的自动携带与使用
当用户再次访问同一个网站时,浏览器会自动将相关Cookie附加到HTTP请求头中,发送给服务器。例如:
Cookie: sessionId=abc123
服务器通过解析请求头中的Cookie信息,可以识别用户的身份,从而实现会话管理、个性化服务等功能。
例如:
- 会话管理
服务器可以通过
sessionId
来识别用户是否已经登录,避免用户每次访问都需要重新登录。 - 个性化服务
服务器可以根据Cookie中存储的用户偏好(如语言、主题等)来提供定制化的内容。
4. Cookie的更新与删除
服务器可以通过再次发送Set-Cookie
指令来更新Cookie的值或属性。例如,服务器可以延长Cookie的有效期,或者修改Cookie的作用域。
要删除一个Cookie,服务器可以发送一个同名的Cookie,并将其过期时间设置为一个已经过去的时间。例如:
Set-Cookie: sessionId=abc123; Max-Age=0
5. Cookie的安全与限制
尽管Cookie在Web开发中非常有用,但它也面临一些安全风险:
- 跨站脚本攻击(XSS)
如果Cookie没有设置
HttpOnly
属性,恶意脚本可能会窃取Cookie中的信息。 - 跨站请求伪造(CSRF)
攻击者可以利用Cookie来伪造用户的请求。
此外,Cookie还有一些限制:
- 大小限制
单个Cookie的大小通常不能超过4KB。
- 数量限制
每个域名下可以存储的Cookie数量是有限的。
6. Cookie的替代方案
随着Web技术的发展,Cookie不再是一些场景下的最佳选择。以下是一些Cookie的替代方案:
- LocalStorage/SessionStorage
HTML5提供的本地存储方案,容量更大(通常5-10MB),但仅限于客户端使用。
- Token认证
使用JWT(JSON Web Token)等令牌来代替Cookie,可以减少服务器存储压力,并提高安全性。
总结
Cookie通过服务器创建、浏览器存储与自动携带的机制,实现了用户状态的持久化。它在会话管理、个性化服务等方面发挥着重要作用,但开发者也需要注意其安全性和限制,并根据实际需求选择合适的存储方案。
面试官:Session和Cookie的区别是什么?如果没有 Cookie 的话 Session 还能用吗?多服务器节点下 Session-Cookie 方案如何做?
Session 的工作原理详解
Session和Cookie类似,也是 Web 开发中用于跟踪用户状态的重要机制,它允许服务器在多个请求之间识别和记住特定的用户,从而实现个性化的用户体验和安全的用户认证。
以下是 Session 工作原理的详细步骤:
1. Session 的创建
- 用户首次访问
当用户第一次访问服务器时,服务器会创建一个新的 Session 对象。这个过程通常是由服务器端的编程语言和框架自动完成的,无需开发者手动干预。
- 生成 Session ID
服务器为 Session 对象分配一个唯一的标识符,称为 Session ID。这个 ID 通常是一个随机生成的字符串,用于在后续的请求中识别和检索对应的 Session 对象。
- 传递 Session ID
服务器将 Session ID 通过某种方式传递给客户端,通常是将其存储在用户的浏览器中,例如作为 Cookie 的值或者在 URL 中作为参数。
2. Session 的存储
- 服务器端存储
Session 对象通常存储在服务器的内存中,但也可以存储在其他地方,如数据库、文件系统等。存储方式取决于服务器的配置和应用程序的需求。
- 内存存储
速度快,但服务器重启或内存不足时数据可能丢失。
- 数据库存储
持久性强,支持 Session 共享和集群化,但速度相对较慢。
- 文件系统存储
简单,但速度较慢,不利于 Session 共享。
3. Session 的传递与使用
- 客户端携带 Session ID
在用户的后续请求中,浏览器会自动将 Session ID(通常通过 Cookie 方式)发送到服务器。
- 服务器验证 Session ID
服务器根据客户端发送的 Session ID,去查找对应的 Session 对象。如果找到,服务器会加载该用户的会话数据。
- 读写 Session 数据
服务器根据当前请求,读取或修改该用户的 Session 数据,以完成各种业务逻辑处理,如保存用户的登录状态、购物车内容等。
4. Session 的销毁
- 会话结束
当会话结束时,服务器会销毁对应的 Session 对象,释放占用的资源。会话结束的情况包括用户关闭浏览器、会话超时、用户主动注销等。
- 超时设置
服务器可以设置一个会话超时时间,当用户在一段时间内没有活动时,服务器会自动销毁 Session 对象。
- 主动销毁
用户主动注销时,服务器应该销毁对应的 Session 对象,以确保用户的隐私和安全。
网页源代码示例(Node.js + Express)
const express = require('express');
const session = require('express-session');
const app = express();
// 配置 Session(存储于服务器内存,有效期 30 分钟)
app.use(session({
secret: 'your-secret-key', // 加密 Session ID 的密钥
resave: false, // 是否强制保存未修改的 Session
saveUninitialized: true, // 是否保存未初始化的 Session
cookie: { maxAge: 1800000 } // Session ID Cookie 的有效期(30 分钟)
}));
// 设置 Session 数据
app.get('/login', (req, res) => {
req.session.user = { id: 123, name: 'Alice' }; // 存储用户信息
res.send('Session 已设置');
});
// 读取 Session 数据
app.get('/profile', (req, res) => {
const user = req.session.user; // 读取用户信息
res.send(`欢迎, ${user.name}`);
});
// 销毁 Session
app.get('/logout', (req, res) => {
req.session.destroy((err) => {
if (err) {
console.error(err);
res.send('注销失败');
} else {
res.send('注销成功');
}
});
});
app.listen(3000, () => {
console.log('服务器已启动,端口 3000 正在监听中...');
});
Session和Cookie的关键区别如下:
特性 |
Cookie |
Session |
---|---|---|
存储位置 | 客户端(浏览器) |
服务器端 |
有效期 | 可长期或会话级 |
服务器配置或用户行为决定 |
安全性 | 较低(客户端可见) |
较高(数据存于服务器) |
存储大小 | ≤4KB |
无固定上限(依赖服务器资源) |
依赖关系 | 可独立使用 |
通常依赖 Cookie 存储 Session ID |
在多服务器节点环境下,实施Session-Cookie方案需要解决的核心问题是Session共享与同步,确保用户在不同服务器间切换时,会话状态保持一致。以下是具体方案及实现步骤:
一、Session共享与同步机制
1. 粘性会话(Sticky Session)
- 原理
通过负载均衡器(如Nginx)将同一用户的所有请求固定分配到同一台服务器。
- 配置示例(Nginx)
upstream backend { ip_hash; # 基于客户端IP的哈希值分配请求 server 192.168.1.100:8080; server 192.168.1.101:8080; }
- 缺点
-
- 服务器负载可能不均衡。
- 单台服务器故障会导致用户会话丢失。
2. Session复制
- 原理
服务器之间实时同步Session数据,确保所有服务器拥有相同的Session信息。
- 实现方式
-
- Tomcat集群
配置
Cluster
节点和DeltaManager
。
- Spring Session
集成Redis等缓存服务器。
- Tomcat集群
- 缺点
-
- 网络带宽消耗大。
- 服务器间耦合度高。
3. 共享存储
- 原理
将Session数据存储在共享存储中(如数据库、缓存服务器、文件系统),所有服务器通过统一接口访问。
- 技术选型
-
- 数据库
MySQL(持久化存储,但性能较低)。
- 缓存服务器
Redis(高性能,支持过期时间)。
- 文件系统
NFS(简单易用,但性能较低)。
- 数据库
二、具体实现步骤(以Redis为例)
1. 技术选型
- Redis
作为共享存储,提供高性能的Session读写。
- Spring Boot
集成Spring Session简化开发。
2. 配置步骤
添加依赖
<!-- Spring Session 依赖 --> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency> <!-- Redis 客户端依赖 --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency>
Redis配置
@Configuration public class RedisConfig { @Bean public RedisConnectionFactory redisConnectionFactory() { return new LettuceConnectionFactory(new RedisStandaloneConfiguration("localhost", 6379)); } }
启用Spring Session
@Configuration @EnableRedisHttpSession public class SessionConfig { // 无需额外配置 }
3. 代码示例
存储Session
@RestController
public class SessionController {
@PostMapping("/login")
public String login(HttpSession session, @RequestParam String username) {
session.setAttribute("username", username);
return "登录成功";
}
}
读取Session
@RestController
public class SessionController {
@GetMapping("/profile")
public String profile(HttpSession session) {
String username = (String) session.getAttribute("username");
return "欢迎, " + username;
}
}
四、总结
方案 |
优点 |
缺点 |
---|---|---|
粘性会话 | 配置简单 |
负载不均衡,单点故障 |
Session复制 | 实时同步 |
网络带宽消耗大 |
共享存储(Redis) | 高性能,扩展性强 |
依赖外部存储 |
Token替代 | 无状态,适合分布式系统 |
需要处理Token生成与验证 |