本篇文章要实现的功能:
- 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 #是否开启swaggerbasic:enable: true #是否开启登录认证username: adminpassword: 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*/@Overridepublic 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));}@Beanpublic 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.集成安全认证,访问接口时携带headerprivate 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;}@Overridepublic 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;}@Overridepublic 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);}}
}