资讯动态

若依前后端分离版Swagger授权访问:从401到带Token联调

发布时间:2026/10/15 23:28:43 来源:尧图企业网站定制
前几天有个哥们儿来找我说他们公司内部联调特别费劲——后端小哥每次改完接口都得手动整理一份接口文档发给前端前端拿到手之后还得对着文档一个个填参数试一天下来光沟通就得花俩小时。后来他们用了若依的RUOYI-VUE前后端分离版本我问他“Swagger配了吗”他说配了Spring Boot一启动就能看到接口列表。我又问“那接口能直接调吗”他愣了一下“不行401提示要登录。”对这就是今天想聊的事——RUOYI-VUE前后端分离版本里Swagger默认是可以打开页面看到接口的但真正点“Try it out”调接口时会因为缺少token而直接鉴权失败。很多团队卡在这要么图省事直接放行所有请求要么干脆不用Swagger靠手写文档。这俩我都不推荐。这篇文章就把完整的“Swagger添加授权访问”方案讲清楚既包含后端的Security配置也包含前端联调时怎么带上去token还有一些我实际踩过的坑。1. 前后端分离权限模型与Swagger暴露的隐患1.1 若依的token鉴权链路先弄明白若依这套框架的鉴权是怎么跑通的。RUOYI-VUE前后端分离版本用的是Spring Security JWT这种组合前端登录成功后拿到一个token后续每一次请求都在请求头里加上Authorization: Bearer token后端过滤器校验token通过后请求才会继续往下走到Controller。整个链路大概是这样的前端发起请求携带token后端Spring Security的过滤器链先跑一遍过滤器从请求头里解析token并校验签名、有效期校验通过后把用户信息塞进SecurityContext然后放行请求校验失败直接抛401请求根本走不到Controller。这套链路本身没什么毛病问题出在Swagger上。Swagger页面本身是一个静态资源打开页面不看接口数据不需要登录但是一旦在Swagger界面上点击“Try it out”去请求具体接口请求头里没有token就会被Spring Security拦截下来返回401。所以很多团队会看到一种“薛定谔的Swagger”现象——接口文档能看但调不通。于是第一反应就是去SecurityConfig里把那些接口路径加入permitAll列表里例如把/swagger-ui/**、/v3/api-docs/**都放行。这里提醒一下放行这些路径是必要的因为Swagger页面加载和API文档JSON数据的基础请求是匿名的但如果把接口本身的业务路径也都偷懒放行那生产环境就等于裸奔了。你要做的是精确放行“Swagger资源路径”而不是放行“业务接口路径”。1.2 为什么直接改SecurityConfig“放行”是坑我见过不少初学者上手若依遇到Swagger调不通直接搜教程在SecurityConfig里加一个/user/login、/system/user/list之类的业务路径到permitAll然后发现接口通了挺高兴。但这就是给项目埋雷。若依的SecurityConfig里面permitAll修饰的是“匿名可访问”的路径这意味着就算不带token也能进得去。假设你把/system/user/list放行了那么任何人只要知道这个路径不登录就能拉取用户列表。而且这个问题还不会立刻暴露等上线后出了数据泄漏事故再去排查成本就高了。我的建议是安全策略上要同时满足“Swagger页面可以用”和“调用必须带token”两点。前者靠放行Swagger相关路径实现后者靠配置Swagger的Authorization参数、把token带进请求头实现。这两步缺一不可。2. 给Swagger加授权访问的两种思路与选型2.1 思路一纯展示模式只放行Swagger资源路径如果你的目只是让团队成员能打开Swagger页面看接口定义、字段说明、枚举值不要求页面里直接调试那么只需要精确放行Swagger的资源路径然后简单配置一下即可。页面能打开接口列表完整但任何实际业务请求依然需要走登录鉴权Swagger调不了也不需要能调。这种情况下配置量很小只需要在SecurityConfig的permitAll列表里加入特定路径即可。但是要注意Swagger页面的文件和接口JSON数据路径不止一个特别是若依整合了knife4j之后涉及到的路径更多遗漏一个就会出现页面样式丢失或接口列表加载不出来的情况。2.2 思路二完整授权访问模式页面内带token调试我比较推荐的是这一种也跟题目的要求完全对应——Swagger页面里可以直接点击“Try it out”然后携带一个真实用户登录后拿到的token去访问接口效果就跟Postman调接口一样。这里面的核心动作有两个后端的Swagger配置类里定义全局参数名字叫Authorization类型是header值是一个占位符比如Bearer前缀实际操作时先在Swagger页面右上角找到“Authorize”按钮把登录拿到的token填进去后续所有请求都会自动带上这个请求头。knife4j在这个场景下体验比原生Swagger更好。knife4j把“Authorize”按钮做得很显眼而且支持按分组保存全局参数每个分组可以独立维护token。对于若依这种多模块项目来说已经够用了。建议直接把思路二作为标准方案。因为思路一不解决前后端联调的实际问题最终前端还是得去拿Postman或者Apifox反而多一套工具。思路二配好后Swagger就是现成的接口调试工具新人上手也快。3. 实操Swagger授权访问完整落地3.1 第一步修改SecurityConfig安全配置先说放行路径。在若依的SecurityConfig里有一段经典的permitAll配置通常在configure(HttpSecurity httpSecurity)方法中长这样.antMatchers( /login, /captchaImage, /register ).permitAll() .antMatchers( HttpMethod.GET, /, /doc.html, /swagger-ui/**, /swagger-resources/**, /v3/api-docs/**, /webjars/** ).permitAll()这里面有几个细节值得注意。/doc.html是knife4j的文档页面入口不是Swagger原生的swagger-ui.html如果你用的是原生Swagger这里就要写/swagger-ui.html。若依新版通常在框架里已经内置了knife4j依赖所以doc.html放行是主路径。第二点是HttpMethod.GET这个限定。为什么只放行GET请求因为Swagger页面加载、API文档JSON获取这些都是GET方法不需要给POST放权。这样处理更精确可以在一定程度上避免有人利用Swagger资源路径做奇怪的跨域访问。第三点/webjars/**必须放行否则swagger页面引用的css、js文件会加载失败页面显示会非常难看。第四点/swagger-resources/**是Swagger资源注册路径knife4j分组显示依赖它不放行的话会出现页面里没有分组信息的问题。3.2 第二步改造SwaggerConfig注入全局Authorization路径放行只是让Swagger页面能打开真正的授权访问需要让Swagger在发送请求时能带上token。若依本身带有SwaggerConfig通常在ruoyi-framework模块的config包下。在这个类里需要构建一个OpenAPI对象并设置全局参数。一个可用的改造示例如下Configuration public class SwaggerConfig { Bean public OpenAPI springOpenAPI() { // 全局安全参数Swagger 页面会显示 Authorize 按钮 ListSecurityScheme securitySchemes Collections.singletonList( new SecurityScheme() .type(SecurityScheme.Type.HTTP) .scheme(bearer) .bearerFormat(JWT) .name(securitySchemeName()) ); return new OpenAPI() .info(new Info() .title(RUOYI-VUE 接口文档) .description(前后端分离版本的接口文档支持携带token调试) .version(1.0.0)) .schemaRequirement(Authorization, new SecurityRequirement().addList(Authorization)) .components(new Components() .addSecuritySchemes(Authorization, new SecurityScheme() .name(Authorization) .type(SecurityScheme.Type.HTTP) .scheme(bearer) .bearerFormat(JWT))); } private String securitySchemeName() { return Authorization; } }这里做的事情说直白一点就是告诉Swagger“本项目的鉴权方式是请求头里的Authorization字段值为Bearer开头的token”。这样Swagger页面就会自动出现一个Authorize按钮点击后输入token后续所有请求自动带上。不过如果用到的是knife4j通常会有更简洁的配置方式直接在application.yml里配置增强功能。若依早期的版本还在用springfox那一套3.0之后升级到springdoc两者配置方式略有区别。如果项目里用的是springfox需要配置的是Docket和globalOperationParameters本质思路一样都是声明全局的header参数名为Authorization。3.3 第三步knife4j分组与生产环境开关若依项目里通常不止一组接口例如系统模块、定时任务模块、代码生成模块都各自有独立的Controller。knife4j支持分组显示配置方式可以按照模块维度拆分多个GroupedOpenApi。实际中我的做法是Bean public GroupedOpenApi systemApi() { return GroupedOpenApi.builder() .group(系统模块) .packagesToScan(com.ruoyi.web.controller.system) .build(); } Bean public GroupedOpenApi monitorApi() { return GroupedOpenApi.builder() .group(监控模块) .packagesToScan(com.ruoyi.web.controller.monitor) .build(); } Bean public GroupedOpenApi commonApi() { return GroupedOpenApi.builder() .group(通用模块) .packagesToScan(com.ruoyi.web.controller.common) .build(); }分组后Swagger页面能按照模块展示接口可读性大大提高。而且每个分组都可以独立使用Authorize不用每次在几百个接口里找目标。生产环境开关这块容易被忽略。当项目上线后Swagger页面仍然可以被访问这是有风险的。至少应该做到生产环境关闭Swagger或者限定只能在内网IP访问。最简单的方式是在application-prod.yml里关闭相关配置。若依的yml文件里通常有类似配置springdoc: api-docs: enabled: false swagger-ui: enabled: falseknife4j的设置knife4j: enable: true production: trueproduction: true的时候生产环境直接禁用knife4j的文档访问功能这个做法很干净。也可以在Nginx层面对/doc.html、/v3/api-docs这些路径做IP白名单限制双保险更稳。3.4 前后端联调中的token传递后端配置完毕只是完成了一半实际联调场景中token从哪来、怎么填进Swagger前端小伙伴们也要清楚。在若依项目里先启动后端服务浏览器打开http://localhost:8080/doc.html然后打开一个新的标签页访问若依的前端登录页比如http://localhost:80输入admin/admin123登录。打开浏览器开发者工具找到Network面板随便找一个带Authorization请求头的请求复制这个请求头里的完整值通常是一长串以Bearer开头的令牌字符串。回到Swagger页面点击右上角的“Authorize”或者knife4j的“Authorize”按钮粘贴这个token进去保存。之后再回到接口列表里点击任意一个接口做调试请求头就会自动携带这个token。这里有个实操细节若依的token是有有效期的默认我记得是30分钟还是2小时不同版本不太一样。token过期之后Swagger调试就会开始报401。这时候不需要重新配Swagger只需要重新登录若依后台拿一个新token再点开Authorize替换掉旧的就行。还有一个比较隐蔽的问题如果你在Swagger里调试的是修改类接口比如POST、PUT、DELETE请求头不光要带Authorization还需要注意若依的防止重复提交拦截器、XSS过滤这类增强功能。有些版本的若依对POST请求还要额外校验Content-Type如果Swagger默认不带application/json会出现参数明明填了但后端收到是空的情况。knife4j一般默认处理得比较好但原生Swagger偶尔会出这个毛病。4. 常见问题与排查经验4.1 Swagger页面可以打开但接口列表为空这个场景出现频率最高。页面能打开但展示不了api-docs数据一般原因就是/v3/api-docs路径没有放行或者扫描包路径错了。排查分两步。第一步看浏览器Network里/v3/api-docs的请求状态码如果是403或者401说明被Security拦截了去SecurityConfig放行路径。如果是404多半是扫描包路径不对或者依赖版本有问题检查SwaggerConfig里的basePackage配置。第二步看控制台有没有报错信息。之前遇到一次接口列表为空打开控制台报的是Failed to load API definition定位到是网关层把/v3/api-docs给拦了。这种情况还得检查网关路由不是只改后端服务就行。4.2 授权访问配置成功但始终返回401这是上面已经提过的老问题。如果Swagger配置了Authorization参数、点了Authorize填了token还是401先做两步判断。第一确认token本身是否有效。用Postman直接请求一个需要鉴权的接口试试如果Postman都401说明token已经过期或根本没登录成功跟Swagger没关系。第二确认请求头是否真的带上了。可以临时在Controller方法里加一行日志输出直接打印请求头里的Authorization值。这个方法很粗暴但非常有效。如果请求头是空的问题一定出在Swagger的全局参数配置上如果带上了但依然401就要看token校验逻辑是不是Bearer前缀格式不对。有个细节容易忽略若依的token校验严格要求请求头格式为Authorization: Bearer token中间有一个空格。有些团队复制token时把Bearer前缀也复制进去了然后Swagger这边配置里又自动加了一个Bearer前缀结果请求变成了Bearer Bearer token后端解析token失败自然就是401了。这个问题我在现场帮人排查过三次每次都是这个原因。4.3 前端联调时CORS跨域报错若依的后端默认是支持跨域访问的但Swagger页面和后端服务如果不在同一个端口上比如前端是8080端口后端是8080端口还是会触发浏览器的CORS策略。Swagger页面本质上是一个前端页面浏览器在调用后端接口时会先发一个OPTIONS预检请求。若依的CorsFilter配置一般能处理这个预检但需要注意如果你在SecurityConfig里额外加了自定义过滤器过滤器顺序不小心把CORS跨域处理逻辑排到了安全认证之后预检请求就会被拦下导致真正的请求发不出去。解决方案是确认CorsFilter在Spring Security过滤器链的最前端或者用CrossOrigin临时写在接口类上应急。生产环境不建议用后者因为前端上线后会走Nginx代理跨域问题基本不存在开发环境的CORS配置只是为了方便本地联调。4.4 刷新token后Swagger还在用旧token这个更像一个使用习惯问题。当你重新登录了若依后台前端页面的token已经变了但Swagger全局参数里还保存着旧的token。如果遇到一些莫名其妙401的请求先想想Swagger的Authorize里填的是不是最新token。另外要提醒一个安全习惯文章开头提到过某些库版本的Swagger Authorization参数是持久化的也就是token会存在浏览器localStorage里。如果电脑是公共设备调试结束后最好在Swagger里手动清空授权信息否则别人打开你的浏览器能直接拿着你的token调接口。4.5 doc.html样式丢失Swagger页面奇丑无比出现这种问题基本是/webjars/**没放行或者静态资源映射失效。浏览器打开开发者工具看下css和js文件的请求状态。如果是404检查一下项目里是否把webjars的静态资源目录给覆盖了如果是403或401检查SecurityConfig。若依的旧版本里有时候WebMvcConfigurer会和SecurityConfig的路径放行产生顺序冲突。解决方法是在WebMvcConfigurer.addResourceHandlers里显式映射/webjars/**到classpath:/META-INF/resources/webjars/。5. 一些值得追加的增强实践5.1 接口分组中增加“匿名接口”和“带认证接口”的区分做后端时间久了你会发现有些接口是登录后才能用的比如获取用户信息、查询列表有些则是完全公开的比如获取验证码、短信发送接口。在Swagger里如果没有区分前端拿到的信息就会比较混乱无从判断哪些接口需要带token。我的个人习惯是给公开接口单独分一个组比如叫“开放接口”并在这个组的描述里写清楚“无需token直接调用”。带认证的接口放在“业务接口”组默认要求带token。这样前端同事一看分组名称就知道该不该填token省去每次问后端的功夫。实现方式是继续使用GroupedOpenApi扫描包路径区分开来。如果项目里开放接口和业务接口混在同一个Controller里那就用pathsToMatch做路径匹配过滤比如所有/auth/**路径归到开放接口组。5.2 结合网关统一处理Swagger聚合很多若依二开项目并不是单服务结构而是把业务拆成多个微服务模块这时候每个服务的Swagger文档是独立的前端要挨个打开联调非常痛苦。解决方案是在网关层做Swagger聚合。若依的网关基于Spring Cloud Gateway可以通过添加Swagger Provider的方式把各个下游服务的api-docs统一聚合到一个入口。前端只需要访问网关的/doc.html就能在一个页面上看到所有微服务的接口列表。这个方案需要额外开发一些配置类写起来不难但要注意聚合后的分组名必须与服务名对得上否则Knife4j无法正确解析每个服务对应的api-docs地址。我见过有些团队一上来就照着网上的聚合教程抄然后发现分组全是乱码或者JSON解析失败折腾一下午才找到问题是网关里服务名大小写不一致。5.3 Swagger注解规范比授权访问本身更重要说到这忍不住多嘴一句Swagger的授权访问配置好之后接口文档能不能用最终取决于团队对接口注解的规范程度。授权只是门锁注解才是这间屋子的装修。若依默认的Controller写法里就有很多ApiOperation、ApiModelProperty注解。如果团队里有人偷懒不写这些注解Swagger页面上接口描述会缺失参数名直接暴露成Java变量名前端看得一头雾水。我强烈建议在开发规范里加上一条所有对外接口必须写ApiOperation所有实体类和DTO的字段必须写ApiModelProperty。另外说一下ApiOperation的value和notes。value是接口摘要notes是详细说明前端关心的是参数到底是什么含义、有哪些枚举值、格式要求是什么。与其让前端反复来问不如在notes里写清楚。这样半小时沟通成本可能只需要一分钟就能解决。6. 收了尾再分享一点个人实操体会给Swagger添加授权访问表面上就是改一个SecurityConfig、加一个全局参数配置但真正把它落地到团队日常开发里还是有不少细节值得打磨。我在实际项目里得到的最大体会是容器化还没有普及的旧项目里老版本若依的springfox依赖切换成springdoc时各种Bean冲突接踵而来这类技术债建议专门安排一点重构时间统一处理掉别等联调出问题再临时切换。另外就是前面反复提到的token有效期问题。有些团队给若依配的JWT有效期特别长甚至长达24小时安全性上其实是有隐患的。Swagger授权访问配置好后测试环境还好生产环境强烈建议配合Nginx或网关做IP白名单限制并且将生产环境knife4j的production开关设为true。要相信一点接口文档是工具但工具暴露在外网就变成了攻击面。控制好这个度比每天纠结哪个接口写不写注释更有意义。如果你正好在折腾若依按这篇文章的步骤走一遍基本十分钟内就能把Swagger授权访问调通。如果中间遇到什么幺蛾子问题欢迎顺着这些排查点挨个过一遍。实在搞不定的情况回头看看你的Spring Security版本、Springdoc版本和knife4j版本是不是互相匹配的多数所谓“玄学问题”其实是版本兼容性在作祟。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑