SpringSecurity 静态资源放行深度详解(解决401认证失败、文件无法访问、URL拦截问题)
实战业务场景 & 报错现象
2.1 业务场景
后端生成 Excel 文件存放在服务器临时目录,通过资源映射配置访问路径:/excel/\*\*,前端、APP 通过 URL 直接下载文件。
2.2 报错信息
{"msg":"认证失败,无法访问系统资源","code":401} |
2.3 报错特征
接口本身无代码报错,后台无异常
浏览器直接访问文件地址,返回 401 未授权
登录后携带 Token 可以正常访问,未登录直接拦截
三、底层原理:为什么会被拦截?
3.1 SpringSecurity 默认拦截规则
SpringSecurity 内置拦截链,默认规则:
所有请求,全部需要认证;没有明确放行的路径,一律拦截。
执行优先级:
客户端发起请求(文件/接口)
进入 SpringSecurity 拦截过滤器链
匹配放行规则(
permitAll\(\))匹配成功:直接放行,无需认证
匹配失败:校验 Token、登录状态,无权限直接抛出401 认证失败
3.2 本次 Excel 文件拦截原因
文件访问地址:http://ip:port/excel/xxx\.xlsx
Security 不会识别这是静态文件,只会识别请求路径/excel/,该路径未配置放行,因此判定为需要登录认证,最终返回 401。
四、核心解决方案:配置资源放行
4.1 放行核心语法
4.1.1 旧版 Security(Ruoyi 通用版本)
.antMatchers("/excel/**").permitAll() |
4.1.2 新版 Security 6.0+
.requestMatchers("/excel/**").permitAll() |
4.2 完整配置代码(Ruoyi 项目通用)
@Override |
protected void configure(HttpSecurity http) throws Exception { |
http |
.authorizeRequests() |
// 放行登录、验证码接口 |
.antMatchers("/login","/captcha/**").permitAll() |
// 放行Excel下载静态资源(核心代码) |
.antMatchers("/excel/**").permitAll() |
// 其余所有请求必须认证 |
.anyRequest().authenticated(); |
} |
4.3 语法详解
| 语法 | 作用说明 |
|---|---|
/excel/\*\* | 匹配规则:以 /excel/ 开头的所有子路径,包含所有Excel文件 |
permitAll\(\) | 永久放行,无需登录、无需Token、无需权限 |
五、关联知识点:静态资源映射 + 放行联动
很多新手只配置放行,依旧无法访问文件,原因是:缺少静态资源映射,二者必须搭配使用。
5.1 两者区别
静态资源映射(WebConfig):告诉 Spring,访问
/excel/去哪里找本地物理文件(解决404)Security放行配置:告诉安全框架,这个路径不用登录(解决401)
5.2 配套静态资源映射代码
@Configuration |
public class WebConfig implements WebMvcConfigurer { |
@Override |
public void addResourceHandlers(ResourceHandlerRegistry registry) { |
// 将 /excel/** 映射到服务器相对路径upload/excel/ |
registry.addResourceHandler("/excel/**") |
.addResourceLocations("file:./upload/excel/"); |
} |
} |
5.3 完整链路(401+404双问题解决)
请求:
/excel/test\.xlsxSecurity 拦截 → 匹配放行规则 → 直接放行(无401)
Spring 资源处理器 → 匹配映射规则 → 读取本地文件(无404)
返回文件流,浏览器/APP 直接下载
六、高频踩坑总结(避坑重点)
6.1 坑1:放行路径和映射路径不一致
映射路径:/file/\*\*,放行路径写:/excel/\*\*,路径不统一,依旧拦截。
解决方案:映射、放行、访问URL三者前缀必须完全一致。
6.2 坑2:新版Security使用旧语法
Security6.0以上禁止使用antMatchers,必须改用requestMatchers,否则项目启动报错。
6.3 坑3:放行位置书写错误
必须写在\.anyRequest\(\)\.authenticated\(\)前面,写在后面放行失
