答案: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 | 未授权 —— 知道你是谁,但不让你进 | 波比已登录,但权限不足 | 找翼王或雁姐开通权限 |
波比的排查步骤:
确认自己是否已登录
打开浏览器开发者工具(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。
确认自己的角色权限
波比是市场部员工,他想访问的是财务部的报表系统。飞翔 OA 的权限模型是 RBAC(基于角色的访问控制):
- 普通员工:只能看自己的考勤、报销
- 部门主管(如翼王):能看本部门数据
- 财务专员(如云吞):能看全公司财务数据
- 系统管理员(如凌叔):能看一切
波比收到 403,说明服务器已经认出了他是"市场部-波比",但判定他没有"财务部报表"的读取权限。
联系权限管理员
波比应该在 OA 里提交权限申请单:
申请人:波比(市场部) 申请权限:财务部月度报表只读权限 申请理由:需要核对市场活动预算执行情况 审批人:翼王(部门主管)→ 雁姐(财务总监)检查是否有 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 的
rolesclaim 来携带权限,权限变更后需要重新签发 Token 或设置较短的过期时间让 Token 自然刷新。