近期将springboox2.x升级到了3.x,索性将swagger2也同步升级到swagger3,具体过程如下。
- <dependency>
- <groupId>org.springdocgroupId>
- <artifactId>springdoc-openapi-starter-webmvc-uiartifactId>
- <version>2.1.0version>
- dependency>
- /**
- * spring doc配置
- */
- @Configuration
- public class SpringDocConfig {
- @Bean
- public OpenAPI restfulOpenAPI() {
- return new OpenAPI()
- .info(new Info().title("springboot3.x demo")
- .description("Spring Boot3 Restful API")
- .version("V1.0.0")
- .license(new License().name("访问SpringDoc官方网站").url("http://springdoc.org")))
- .externalDocs(new ExternalDocumentation()
- .description("欢迎访问LDY的技术博客")
- .url("https://blog.csdn.net/ldy1016"));
- }
-
- }
启动项目,在浏览器输入{ip}:{端口}/swagger-ui/index.html,查看效果,如127.0.0.1:8080/swagger-ui/index.html

首先来看一下swagger2和swagger3中注解的对应关系,方便使用swagger2的同学升级到swagger3
| swagger2 | swagger3 | 说明 |
| @Api | @Tag | 用在请求的类上,表示对类的说明 |
| @ApiIgnore | @Hidden | 隐藏显示 |
| @ApiImplicitParam | @Parameter | 用在请求方法上,指定具体某一个请求参数的详细信息 |
| @ApiImplicitParams | @Parameters | 用在请求方法上,表示一组参数的说明 |
| @ApiModel | @Schema | 用于请求或者响应类上,说明请求或者响应数据 |
| @ApiModelProperty | @Schema | 用在属性上,描述响应类的属性用,swagger2中的hidden = true属性相当于swagger3中 的accessMode = READ_ONLY属性 |
| @ApiOperation | @Operation | 用在请求的方法上,说明方法的用途、作用,对应注解中swagger2中的value和notes属性对应swagger3中的summary和description属性 |
| @ApiParam | @Parameter | 描述参数信息 |
参考示例:
@Tag 描述整个类
- @Tag(name = "用户管理")
- @RestController
- @RequestMapping("/user")
- public class UserController {}
@Operation 用在请求的方法上,说明方法的用途、作用
- @Operation(summary = "查询用户列表接口",description = "部门用户信息")
- @GetMapping("/list")
- public List
list(@RequestBody UserQueryParam param) { -
- //TODO 查询用户信息并返回
-
- return null;
- }
@Schema 用于请求或者响应类上,说明请求或者响应数据,用在属性上,描述响应类的属性用
- @Data
- @Schema(title = "用户信息查询参数")
- public class UserQueryParam implements Serializable {
- private static final long serialVersionUID = 4159622041608936674L;
-
- @Schema(title = "部门")
- private String department;
-
- @Schema(title = "姓名")
- private String name;
-
- @Schema(title = "性别",allowableValues = "0,1",example = "0")
- private Integer sex;
-
- }
打开swagger页面查看效果


swagger3未授权访问的路径主要包括/v3/api-docs和/swagger-ui/index.html。
本人提供的解决方案就是通过过滤器的方式对请求进行验证,请求的时候需要在链接后面加上我们自定义的token参数,通过验证token判断是否是合法的访问,注意,添加过滤器后需要在启动类上加上@ServletComponentScan注解才能生效,具体实现如下:
- import jakarta.servlet.Filter;
- import jakarta.servlet.FilterChain;
- import jakarta.servlet.FilterConfig;
- import jakarta.servlet.ServletException;
- import jakarta.servlet.ServletRequest;
- import jakarta.servlet.ServletResponse;
- import jakarta.servlet.annotation.WebFilter;
- import jakarta.servlet.http.HttpServletRequest;
- import jakarta.servlet.http.HttpServletResponse;
- import lombok.extern.slf4j.Slf4j;
-
- /**
- * 解决swagger-ui 未授权访问漏洞,需要在启动类加@ServletComponentScan注解
- *
- * @author ldy
- * @since V1.0.0
- */
- @Slf4j
- @WebFilter(urlPatterns = {"/v3/api-docs",
- "/swagger-ui/index.html"}, filterName = "springDocFilter")
- public class SpringDocFilter implements Filter {
-
- /**
- * 访问swagger的token
- */
- @Value("${swagger.token:123@abc}")
- private String swaggerToken;
-
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- Filter.super.init(filterConfig);
- }
-
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
- throws IOException, ServletException {
- HttpServletRequest request = (HttpServletRequest) servletRequest;
- HttpServletResponse response = (HttpServletResponse) servletResponse;
- log.info("do springDocFilter,url:{}", request.getRequestURL());
- // 请求来源地址
- String referer = request.getHeader("referer");
- log.info("referer is {}", referer);
-
- /**
- * 1、请求来源地址为空,判断token是否匹配 2、请求来源地址不为空,判断来源地址是否包含正确的token
- */
- if (StringUtils.isBlank(referer)) {
- // 获取token
- String token = request.getParameter("token");
- log.info("token is {}", token);
- // 来源地址为空,判断token是否匹配
- if (!StringUtils.equals(swaggerToken, token)) {
- log.error("禁止未授权访问,url:{}", request.getRequestURL());
- response.setStatus(403);
- servletResponse.setContentType("application/json");
- servletResponse.setCharacterEncoding("UTF-8");
- servletResponse.getWriter().write(JsonUtil.toJsonString(DJResult.error(-1, "禁止未授权访问", "")));
- return;
- }
- } else if (!referer.contains(swaggerToken)) {
- log.warn("禁止未授权访问,url:{}", request.getRequestURL());
- response.setStatus(403);
- servletResponse.setContentType("application/json");
- servletResponse.setCharacterEncoding("UTF-8");
- servletResponse.getWriter().write(JsonUtil.toJsonString(DJResult.error(-1, "禁止未授权访问", "")));
- return;
- }
-
-
- filterChain.doFilter(servletRequest, servletResponse);
- }
-
- @Override
- public void destroy() {
- Filter.super.destroy();
- }
- }
通过添加如上所示的过滤器后,我们就可以通过在路径后面加上token参数进行访问文档地址了,如:127.0.0.1:8080/swagger-ui/index.html?token=123@abc。
没有加token参数或者token参数匹配不上的请求会直接返回“禁止未授权访问”。这里的token尽量设置复杂一点。
