近期将springboox2.x升级到了3.x,索性将swagger2也同步升级到swagger3,具体过程如下。
一、添加maven依赖
<dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>2.1.0</version>
</dependency>
二、编写SpringDoc配置类
/*** spring doc配置*/
@Configuration
public class SpringDocConfig {@Beanpublic 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
三、添加swagger3注解
首先来看一下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<UserVO> 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页面查看效果
四、自定义过滤器,防止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;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}@Overridepublic 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)) {// 获取tokenString 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);}@Overridepublic void destroy() {Filter.super.destroy();}
}
通过添加如上所示的过滤器后,我们就可以通过在路径后面加上token参数进行访问文档地址了,如:127.0.0.1:8080/swagger-ui/index.html?token=123@abc。
没有加token参数或者token参数匹配不上的请求会直接返回“禁止未授权访问”。这里的token尽量设置复杂一点。