- Add request.js for unified API calls with loading/error handling - Add service page (service type listing) - Fix hospital list to load from API with proper image URL construction - Add service types dynamic loading on index page - Various mini program improvements (order, care, wallet pages) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2.6 KiB
2.6 KiB
Spring Security anonymous() vs permitAll() 踩坑记录
现象
后台管理系统登录后,访问 业务管理 > 医院管理 页面提示"系统接口异常",后端返回:
{
"timestamp": "2026-05-25T03:08:28.944+08:00",
"status": 403,
"error": "Forbidden",
"path": "/system/hospital/list"
}
直接用 curl 不带 token 调用接口正常返回 200,但带上 JWT token 就返回 403。
根因
SecurityConfig.java 中 /system/hospital/list 被配置为 .anonymous():
.antMatchers("/login", ..., "/system/hospital/list", ...).anonymous()
Spring Security 中两种访问控制的区别:
| 配置 | 含义 | 匿名用户 | 已认证用户 |
|---|---|---|---|
.permitAll() |
所有用户均可访问 | 允许 | 允许 |
.anonymous() |
仅匿名用户可访问 | 允许 | 拒绝(403) |
当后台管理员登录后,JWT 过滤器为请求注入了认证信息(不再是匿名用户),Spring Security 判定已认证用户无权访问 .anonymous() 资源,返回 403。
而小程序端调用该接口时不带 token(匿名),所以一直正常。
修复
将需要同时被"小程序(匿名)"和"后台(已认证)"访问的接口,从 .anonymous() 移至 .permitAll():
// 仅匿名用户 —— 登录、注册、验证码等
.antMatchers("/login","/appLogin","/system/msm","/smsLogin",
"/register","/captchaImage","/weixinLogin","/getUserToken",
"/system/weixin/wxPayNotify","/system/weixin/wxRefundNotify")
.anonymous()
// 所有用户均可访问 —— 被小程序和后台共同使用的数据接口
.antMatchers("/system/user/getAppIndexInfo","/system/hospital/list",
"/system/config/configKey/**","/system/nursing/published",
"/system/nursing/view/**","/system/serviceType/enabled")
.permitAll()
经验总结
.anonymous()是排他性的 —— 已登录用户访问会直接 403,不要用于需要同时支持前台和后台的 API.permitAll()vs.anonymous()选择标准:- 登录/注册页面等"仅限未登录用户" →
.anonymous() - 公开数据接口(小程序+后台共用) →
.permitAll()
- 登录/注册页面等"仅限未登录用户" →
- 排查 403 时先看 SecurityConfig —— 即使 API 直接 curl 正常,带 token 就可能因认证状态不同而变化
- 排查思路:逐层验证 API → 数据库 → 菜单路由 → Nginx 代理 → Security 权限配置
相关文件
rlz/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.javarlz-ui/src/views/system/hospital/index.vuerlz-ui/src/utils/request.js(前端错误拦截器)