本篇文章要实现的功能:
- 1.集成swagger
- 2.集成swagger登录功能,访问 /swagger-ui.html需要先登录
- 3.集成安全认证,访问接口时携带header
请求接口时携带了上一步输入的header参数和值
1.集成swagger
jdk11,SpringBoot 2.7.13
pom.xml依赖swagger2.10.5
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.10.5</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.10.5</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-spring-webmvc</artifactId>
<version>2.10.5</version>
</dependency>
application.yml
swagger:
enable: true #是否开启swagger
basic:
enable: true #是否开启登录认证
username: admin
password: admin
2.集成swagger登录功能,访问 /swagger-ui.html需要先登录
新建 Swagger2Config
import com.zypcy.mono.interceptor.SwaggerInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.handler.MappedInterceptor;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableWebMvc
@EnableSwagger2WebMvc
@ConditionalOnProperty(
name = {"swagger.enable"},
havingValue = "true",
matchIfMissing = false
)
public class Swagger2Config implements WebMvcConfigurer {
@Value("${spring.profiles.active}")
private String active;
@Value("${swagger.basic.username:admin}")
private String username;
@Value("${swagger.basic.password:admin}")
private String password;
private String basePackage = "com.zypcy.mono.controller";
/**
* 开放swagger-ui.html资源
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
WebMvcConfigurer.super.addResourceHandlers(registry);
}
/* 在此处配置拦截器,要不然拦不到swagger的静态资源 */
@Bean
@ConditionalOnProperty(name = "swagger.basic.enable", havingValue = "true")
public MappedInterceptor getMappedInterceptor() {
return new MappedInterceptor(new String[]{"/swagger-ui.html", "/v2/api-docs", "/webjars/**"}, new SwaggerInterceptor(username, password));
}
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.enable(!"prod".equals(active))
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage(basePackage))
.paths(PathSelectors.any())
.build()
.securitySchemes(securitySchemes())
.securityContexts(securityContexts());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Mono API 接口文档")
.description("Mono REST API 接口文档")
.termsOfServiceUrl("")
.contact(new Contact("zhuyu", "https://zhuyu.blog.csdn.net", "645906265@qq.com"))
.license("Mono License Version 2.0")
.licenseUrl("http://www.xxx.xxx/licenses/LICENSE-2.0")
.version("1.0")
.build();
}
//3.集成安全认证,访问接口时携带header
private List<SecurityScheme> securitySchemes() {
List<SecurityScheme> res = new ArrayList<>();
res.add(new ApiKey("AppId", "AppId", "header"));
res.add(new ApiKey("Authorization", "Authorization", "header"));
return res;
}
private List<SecurityContext> securityContexts() {
List<SecurityContext> res = new ArrayList<>();
res.add(SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex("/.*"))
.build());
return res;
}
private List<SecurityReference> defaultAuth() {
List<SecurityReference> res = new ArrayList<>();
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
res.add(new SecurityReference("AppId", authorizationScopes));
res.add(new SecurityReference("Authorization", authorizationScopes));
return res;
}
/**
* 添加header,调用代码:this.header("x-request-info", "string", false, "appId=101;token=a256f4c4f38a76115355d2d039e2882e;")
* @param name
* @param type
* @param required
* @param defaultValue
* @return
*/
private Parameter header(String name, String type, boolean required, String defaultValue) {
ParameterBuilder param = new ParameterBuilder();
return param.name(name).modelRef(new ModelRef(type)).parameterType("header").defaultValue(defaultValue).required(required).build();
}
}
创建拦截器 SwaggerInterceptor
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Base64;
/**
* @Description:
* @Author: zhuyu
* @Date: 2023/11/22 20:44
*/
public class SwaggerInterceptor implements HandlerInterceptor {
private String username;
private String password;
public SwaggerInterceptor(String username, String password) {
this.username = username;
this.password = password;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String authorization = request.getHeader("Authorization");
boolean isAuthSuccess = httpBasicAuth(authorization);
if (!isAuthSuccess) {
response.setCharacterEncoding("utf-8");
response.setStatus(401);
response.setHeader("WWW-authenticate", "Basic realm=\"Realm\"");
try (PrintWriter writer = response.getWriter()) {
writer.print("Forbidden, unauthorized user");
}
}
return isAuthSuccess;
}
public boolean httpBasicAuth(String authorization) throws IOException {
if (authorization != null && authorization.split(" ").length == 2) {
String userAndPass = new String(Base64.getDecoder().decode((authorization.split(" ")[1])));
String username = userAndPass.split(":").length == 2 ? userAndPass.split(":")[0] : null;
String password = userAndPass.split(":").length == 2 ? userAndPass.split(":")[1] : null;
if (this.username.equals(username) && this.password.equals(password)) {
return true;
}
}
return false;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
String uri = request.getRequestURI();
AntPathMatcher pathMatcher = new AntPathMatcher();
if (!pathMatcher.match("/swagger-ui.html", uri) && !pathMatcher.match("/webjars/**", uri)) {
response.setStatus(404);
return;
}
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("classpath:/META-INF/resources" + uri);
if (resources != null && resources.length > 0) {
FileCopyUtils.copy(resources[0].getInputStream(), response.getOutputStream());
} else {
response.setStatus(404);
}
}
}