近期将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 {
@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
三、添加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;
@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尽量设置复杂一点。