飞翔飞翔
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
  • 学习路径
  • HTTP 基础

    • 认识HTTP协议与应用层定位
    • HTTP消息格式与报文结构
    • HTTP请求方法与幂等性
    • HTTP状态码详解
  • 连接与缓存

    • HTTP持久连接与版本演进
    • HTTP缓存机制
  • 状态与协商

    • Cookie与Session状态管理
    • HTTP重定向与内容协商
    • HTTP条件请求与范围请求
  • 安全与加密

    • HTTP认证机制
    • HTTPS与TLS握手
  • 协议演进

    • HTTP2核心特性
    • HTTP3与QUIC
  • 架构与实战

    • HTTP代理服务器与Web缓存
    • HTTP常见攻击与防御
    • HTTP实践工具与抓包分析

答案:HTTP状态码详解

如果飞翔公司把官网从 http://feixiang.net 永久迁移到 https://www.feixiang.net,应该返回 301 还是 302?为什么?

应该返回 301(Moved Permanently)。

原因分析:

这次迁移是永久性的——飞翔公司决定以后所有用户都应该访问 https://www.feixiang.net,旧的 http://feixiang.net 不再作为正式入口。这种情况下:

  • 301 表示"资源已永久移动到新的 URL",浏览器收到后会缓存这个重定向。下次用户再访问 http://feixiang.net,浏览器直接从缓存中知道要去 https://www.feixiang.net,不再向旧地址发请求。这减少了服务器压力,也加快了用户访问速度。
  • 302 表示"资源临时位于其他 URL",浏览器不会缓存重定向。每次访问旧地址都要先问服务器"还在不在",然后才被指到新地址。如果飞翔公司是临时维护、A/B 测试,才用 302。

凌叔的 Nginx 配置:

server {
    listen 80;
    server_name feixiang.net www.feixiang.net;
    
    # 永久重定向到 HTTPS 且带 www
    return 301 https://www.feixiang.net$request_uri;
}

server {
    listen 443 ssl;
    server_name www.feixiang.net;
    # SSL 证书配置...
}

验证效果:

# 第一次访问旧地址
curl -I http://feixiang.net
# HTTP/1.1 301 Moved Permanently
# Location: https://www.feixiang.net/

# 浏览器缓存 301 后,后续直接跳转
# 用 Chrome 开发者工具可以看到:
# Status: 307 Internal Redirect (from disk cache)
# 这是浏览器用缓存的 301 规则直接跳转,根本没发请求到服务器

注意事项:

301 缓存很"顽固",如果凌叔配置错了(比如把 301 指向了一个测试服务器),用户的浏览器会记住这个错误很久。所以上线前,凌叔总是先用 302 测试,确认无误后再改成 301。

另外,从 HTTP 到 HTTPS 的升级,还应该配合 HSTS(HTTP Strict Transport Security) 响应首部,让浏览器强制用 HTTPS 访问,防止中间人攻击:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

波比访问内部系统时遇到 403,他应该怎么排查?(提示:对比 401 和 403 的区别)

首先明确 401 和 403 的本质区别:

状态码含义谁的问题解决方式
401 Unauthorized未认证 —— 不知道你是谁波比没登录,或 Token 过期重新登录,获取新 Token
403 Forbidden未授权 —— 知道你是谁,但不让你进波比已登录,但权限不足找翼王或雁姐开通权限

波比的排查步骤:

  1. 确认自己是否已登录

    打开浏览器开发者工具(F12)→ Network 面板,查看请求是否携带了 Cookie 或 Authorization 首部。

    # 用 curl 检查请求是否带认证信息
    curl -I http://oa.feixiang.net/finance/report \
      -H "Cookie: session_id=xxx" \
      -H "Authorization: Bearer xxx"
    

    如果没带认证信息就收到 403,先尝试重新登录。但通常没带认证会返回 401,不是 403。

  2. 确认自己的角色权限

    波比是市场部员工,他想访问的是财务部的报表系统。飞翔 OA 的权限模型是 RBAC(基于角色的访问控制):

    • 普通员工:只能看自己的考勤、报销
    • 部门主管(如翼王):能看本部门数据
    • 财务专员(如云吞):能看全公司财务数据
    • 系统管理员(如凌叔):能看一切

    波比收到 403,说明服务器已经认出了他是"市场部-波比",但判定他没有"财务部报表"的读取权限。

  3. 联系权限管理员

    波比应该在 OA 里提交权限申请单:

    申请人:波比(市场部)
    申请权限:财务部月度报表只读权限
    申请理由:需要核对市场活动预算执行情况
    审批人:翼王(部门主管)→ 雁姐(财务总监)
    
  4. 检查是否有 URL 拼写错误

    有时候 403 是因为访问了不该访问的路径,比如:

    http://oa.feixiang.net/admin/user-list  # 管理员路径,普通员工 403
    http://oa.feixiang.net/api/admin/config  # 系统配置接口,普通员工 403
    

波比排查 checklist:

# Step 1: 检查认证状态
curl -v http://oa.feixiang.net/finance/report 2>&1 | grep "HTTP/"
# 如果是 401 → 去登录
# 如果是 403 → 继续排查

# Step 2: 检查自己的角色和权限
curl http://oa.feixiang.net/api/user/info \
  -H "Authorization: Bearer $TOKEN" | jq '.roles'
# 输出:["market_staff"] —— 只有市场部员工角色,没有财务权限

# Step 3: 查看系统权限矩阵(如果有开放接口)
curl http://oa.feixiang.net/api/permissions/matrix \
  -H "Authorization: Bearer $TOKEN" | jq '.finance_report.read'
# 输出:false —— 确认没有权限

波比最后找翼王签字,雁姐审批后,凌叔在后台给波比加了 finance_report_read 角色,再次访问就返回 200 了。


凌叔发现服务器频繁返回 502,可能是什么原因?他应该检查哪些环节?

502 Bad Gateway 的含义:

502 表示"网关或代理服务器从上游服务器收到了无效响应"。在飞翔公司的架构中,通常是 Nginx(反向代理/网关)无法从后端的 Node.js/Java 应用服务器获得正确响应。

可能原因及排查环节:

1. 后端服务宕机或崩溃

这是最常见的原因。凌叔部署了 3 台应用服务器处理 OA 请求,如果其中一台因为内存溢出(OOM)崩溃,Nginx 把请求转发到这台死掉的机器,就会返回 502。

# 检查后端进程是否存活
ps aux | grep node
# 或者
systemctl status feixiang-oa-backend

# 查看崩溃日志
tail -n 100 /var/log/feixiang-oa/error.log
# 可能看到:FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed

2. 后端服务过载,无法及时响应

年会报名高峰期,波比和云吞同时涌入,后端连接数打满。Nginx 的 proxy_connect_timeout 默认 60 秒,如果后端在超时时间内没响应,Nginx 返回 502。

# 检查后端连接数
ss -s | grep TCP
# 或者查看应用监控
 curl http://localhost:9090/metrics | grep active_connections

# Nginx 错误日志
 tail -f /var/log/nginx/error.log
# [error] upstream timed out (110: Connection timed out) while connecting to upstream

3. Nginx 与后端之间的网络问题

防火墙规则变更、Docker 容器网络中断、VPC 路由异常,都可能导致 Nginx 连不上后端。

# 从 Nginx 服务器测试后端连通性
curl -v http://backend-01:8080/health
# 如果连接失败,检查网络和防火墙

# 检查防火墙规则
iptables -L -n | grep 8080

4. 后端返回了非法响应

比如后端程序 bug,在 HTTP 响应还没发完时就异常退出,Nginx 收到不完整的响应,也会报 502。

# 直接访问后端,绕过 Nginx,看响应是否完整
curl -v http://backend-01:8080/api/test
# 如果后端直接断开连接或返回畸形数据,问题在后端代码

凌叔的排查流程图:

发现 502
  → 检查后端进程是否存活?
    → 否 → 重启服务,查崩溃原因(OOM/代码bug)
    → 是 → 检查后端负载(CPU/内存/连接数)
      → 过高 → 扩容或限流
      → 正常 → 检查网络连通性
        → 不通 → 检查防火墙/网络配置
        → 通 → 检查后端日志,看是否返回异常响应

预防措施:

# Nginx 健康检查配置
upstream backend {
    server backend-01:8080 max_fails=3 fail_timeout=30s;
    server backend-02:8080 max_fails=3 fail_timeout=30s;
    server backend-03:8080 backup;  # 备用节点
}

凌叔还配置了告警:当 502 频率超过每分钟 10 次时,自动发钉钉消息给运维值班人员。


设计一个场景:星宇在飞翔 OA 系统中依次遇到 401 → 登录后遇到 403 → 找翼王开通权限后最终看到 200。用一段话描述这个完整过程。

场景描述:

星宇是飞翔公司新入职的飞行调度专员,第一天上班需要查看"航班动态监控大屏"来跟踪风速负责的各航线实时状态。他打开浏览器输入 http://oa.feixiang.net/flight-dashboard,系统立即返回 401 Unauthorized,页面跳转到登录界面提示"请先登录"——原来星宇还没输入账号密码,服务器不认识他是谁。星宇输入工号和初始密码完成登录,浏览器拿到了凌叔签发的 JWT Token,再次访问大屏地址,这次却返回 403 Forbidden,页面显示"您没有权限访问该资源"——服务器已经认出他是"飞行调度部-星宇",但查询 RBAC 权限表后发现,新员工默认只有基础 OA 权限,"航班动态监控"属于高级调度权限,需要部门主管审批开通。星宇在 OA 的权限申请模块填写工单,说明"工作需要查看实时航班状态以协助风速做调度决策",提交给部门主管翼王。翼王审批通过后,系统自动通知凌叔在后台为星宇的角色数组追加 flight_dashboard_read 权限。星宇刷新页面,这次请求携带的 Token 被权限中间件解析出包含 flight_dashboard_read,服务器返回 200 OK,大屏成功加载,星宇终于看到了风速负责的京沪航线实时飞行状态图,开始了他第一天的工作。

对应的 HTTP 报文流:

# 第1次请求:未登录 → 401
GET /flight-dashboard HTTP/1.1
Host: oa.feixiang.net
# 缺少 Cookie/Authorization

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="oa.feixiang.net"
Content-Type: text/html

<html>...登录页面...</html>

---

# 第2次请求:已登录但无权限 → 403
GET /flight-dashboard HTTP/1.1
Host: oa.feixiang.net
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...(星宇的Token)

HTTP/1.1 403 Forbidden
Content-Type: application/json

{"error": "insufficient_permissions", "required": ["flight_dashboard_read"]}

---

# 第3次请求:权限开通后 → 200
GET /flight-dashboard HTTP/1.1
Host: oa.feixiang.net
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...(更新后的Token,包含新权限)

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 15240

<html>...航班动态监控大屏...</html>

这个场景的教育意义:

  • 401 和 403 是完全不同的排查方向,很多新手混为一谈。
  • 权限管理是分层的:认证(Authentication,知道你是谁)→ 授权(Authorization,决定你能做什么)。
  • 企业系统的权限变更需要审批流,不是技术问题,是管理流程问题。翼王的审批环节体现了飞翔公司的内控合规。
  • Token 的权限声明要及时更新,凌叔在飞翔公司使用 JWT 的 roles claim 来携带权限,权限变更后需要重新签发 Token 或设置较短的过期时间让 Token 自然刷新。