一、背景
最近在做一个 Spring Boot 2.x + Vue 的前后端分离项目,部署时使用 Nginx 1.20.2 作为反向代理。前端页面能正常打开,但点击登录按钮后没有任何反应,没有跳转,没有提示,像死了一样。打开浏览器 F12 查看网络请求,发现登录接口返回了 404。于是开始了漫长的踩坑之旅。
二、环境说明
| 组件 | 版本 |
|---|---|
| Spring Boot | 2.x |
| JDK | 8 |
| Nginx | 1.20.2 |
| 前端 | Vue 2.x |
| 数据库 | MySQL |
| 操作系统 | Windows |
三、踩坑实录
第一阶段:Nginx 路径不匹配 → 404
现象:F12 网络面板显示请求 POST /api/employee/login 返回 404。
查看 Nginx access.log,发现请求确实到了 Nginx:
127.0.0.1 - - [08/Aug/2026:21:04:34 +0800] "POST /api/employee/login HTTP/1.1" 404 96
排查过程:
后端接口路径为:
@RestController
@RequestMapping("/admin/employee")
public class EmployeeController {
@PostMapping("/login")
public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO login) {
// ...
}
}
即完整路径为 /admin/employee/login。
而 Nginx 配置中:
location /api/ {
proxy_pass http://127.0.0.1:8080/;
}
由于 proxy_pass 末尾带 /,/api/employee/login 被转发成了 /employee/login,少了一层 /admin,导致后端匹配不到接口。
解决方案:
location /api/ {
proxy_pass http://127.0.0.1:8080/admin/; # 加上 /admin/
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
第二阶段:配置变量错误 → 502
现象:F12 网络面板中偶尔出现 502 Bad Gateway。
排查过程:配置中有一行 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;,但由于 Windows 记事本字体渲染问题,下划线在屏幕显示上容易被误认为空格,导致 Nginx 解析时无法识别该变量,从而报错。
解决方案:删掉 X-Forwarded-For 相关配置(非必须),或者确保变量名拼写完全正确。精简后的配置:
location /api/ {
proxy_pass http://127.0.0.1:8080/admin/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
提示:
X-Forwarded-For用于获取客户端真实 IP,在登录功能中非必须,删除不影响正常使用。
第三阶段:浏览器直接访问 → 400 Bad Request
现象:为了验证后端是否正常,直接在浏览器地址栏访问 http://127.0.0.1:8080/admin/employee/login,返回 Spring Boot 默认的 400 Bad Request 白页。
排查过程:后端接口使用 @PostMapping("/login"),只接受 POST 请求。浏览器地址栏访问默认是 GET 请求,因此返回 400。
解决方案:使用 Postman/ApiFox 等工具发送 POST 请求进行测试,或者确保前端登录请求为 POST 方式。
提示:F12 网络面板中可以看到前端请求的方法类型,确认是 POST 即可。
第四阶段:转发成功但密码错误
现象:Nginx 转发成功后,登录接口返回 200,但响应内容为:
{
"code": 0,
"msg": "密码错误",
"data": null
}
排查过程:查看后端 EmployeeServiceImpl.login 方法:
public Employee login(EmployeeLoginDTO employeeLoginDTO) {
String username = employeeLoginDTO.getUsername();
String password = employeeLoginDTO.getPassword();
Employee employee = employeeMapper.getByUsername(username);
if (employee == null) {
throw new AccountNotFoundException("账号不存在");
}
// 密码比对 — 先加密再比对
password = DigestUtils.md5DigestAsHex(password.getBytes());
if (!password.equals(employee.getPassword())) {
throw new PasswordErrorException("密码错误");
}
if (employee.getStatus() == StatusConstant.DISABLE) {
throw new AccountLockedException("账号被锁定");
}
return employee;
}
前端传入的明文密码会被 MD5 加密后再与数据库比对。查看数据库 employee 表,发现密码字段存的是明文 123456,而 MD5 加密后的 123456 为 e10adc3949ba59abbe56e057f20f883e,二者不匹配。
原因分析:项目初始化时导入的 SQL 脚本直接插入了明文密码,但代码中一直存在 MD5 加密比对逻辑,导致历史数据与代码逻辑不一致。
解决方案:将数据库中密码字段更新为 MD5 密文:
UPDATE employee SET password = 'e10adc3949ba59abbe56e057f20f883e' WHERE username = 'admin';
更新后,使用明文密码 123456 登录成功。
第五阶段:一劳永逸的解决方式
为了让后续新增的员工不再出现同样的问题,修改新增员工代码,存入数据库前自动加密:
employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
其中 PasswordConstant.DEFAULT_PASSWORD 定义为:
public static final String DEFAULT_PASSWORD = "123456";
这样所有新增员工都会自动加密存储,登录时加密比对即可匹配。
四、最终 Nginx 配置
server {
listen 80;
server_name localhost;
location / {
root html/sky;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# 反向代理 — 管理端
location /api/ {
proxy_pass http://127.0.0.1:8080/admin/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 反向代理 — 用户端
location /user/ {
proxy_pass http://webservers/user/;
}
# WebSocket
location /ws/ {
proxy_pass http://webservers/ws/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
}
}
五、如何快速排查类似问题
如果以后再遇到前端请求无响应的情况,按这个顺序查:
- 看 F12 网络面板:确认请求 URL、状态码、响应内容。
- 看 Nginx access.log:确认请求是否到达 Nginx。
- 看后端控制台:在接口入口加
System.out.println("请求进来了"),确认请求是否进入后端。 - 直接测后端接口:用 Postman 发请求,绕过 Nginx,确认后端本身是否正常。
六、总结
这次登录踩坑经历,本质上是三个独立问题的叠加:
- Nginx 路径转发问题:
proxy_pass路径要匹配后端接口的完整路径。 - 数据库历史数据问题:SQL 脚本存的明文与代码加密逻辑不一致。
- 配置文件编码/显示问题:下划线在部分编辑器中显示异常,影响配置解析。
排查时冷静分析,从 F12 出发,逐层向上游(Nginx → 后端 → 数据库)推进,总能定位到根因。
希望这篇踩坑记录能帮到遇到类似问题的朋友。

583

被折叠的 条评论
为什么被折叠?



