All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.taotao.boot.springdoc.configuration.SpringdocAutoConfiguration Maven / Gradle / Ivy

/*
 * Copyright (c) 2020-2030, Shuigedeng ([email protected] & https://blog.taotaocloud.top/).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.taotao.boot.springdoc.configuration;

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import com.taotao.boot.common.constant.StarterName;
import com.taotao.boot.common.utils.ip.IpUtils;
import com.taotao.boot.common.utils.log.LogUtils;
import com.taotao.boot.springdoc.properties.SpringdocProperties;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Paths;
import io.swagger.v3.oas.models.headers.Header;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.media.IntegerSchema;
import io.swagger.v3.oas.models.media.StringSchema;
import io.swagger.v3.oas.models.security.OAuthFlow;
import io.swagger.v3.oas.models.security.OAuthFlows;
import io.swagger.v3.oas.models.security.Scopes;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.security.SecurityScheme.In;
import io.swagger.v3.oas.models.servers.Server;
import org.apache.commons.lang3.StringUtils;
import org.dromara.hutool.core.collection.CollUtil;
import org.springdoc.core.customizers.OpenApiCustomizer;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * SwaggerAutoConfiguration
 *
 * @author shuigedeng
 * @version 2022.03
 * @since 2020/4/30 10:10
 */
@AutoConfiguration
// @Configuration
@EnableKnife4j
@EnableConfigurationProperties({SpringdocProperties.class})
@ConditionalOnProperty(
	prefix = SpringdocProperties.PREFIX,
	name = "enabled",
	havingValue = "true",
	matchIfMissing = true)
//第一种.集成OAuth2登录认证
//@OpenAPIDefinition(
//	info = @io.swagger.v3.oas.annotations.info.Info(
//		// 标题
//		title = "${custom.info.title:'example-api'}",
//		// 版本
//		version = "${custom.info.version:'0.0.1'}",
//		// 描述
//		description = "${custom.info.description:'这是一个使用SpringDoc生成的在线文档.'}",
//		// 首页
//		termsOfService = "${custom.info.termsOfService:'http://127.0.0.1:8080/example/test01'}",
//		// license
//		license = @io.swagger.v3.oas.annotations.info.License(
//			name = "${custom.license.name:'Apache 2.0'}",
//			// license 地址
//			url = "http://127.0.0.1:8080/example/test01"
//		)
//	),
//	// 这里的名字是引用下边 @SecurityScheme 注解中指定的名字,指定后发起请求时会在请求头中按照OAuth2的规范添加token
//	security = @io.swagger.v3.oas.annotations.security.SecurityRequirement(name = "${custom.security.name:Authenticate}")
//)
//@SecuritySchemes({@io.swagger.v3.oas.annotations.security.SecurityScheme(
//	// 指定 SecurityScheme 的名称(OpenAPIDefinition注解中的security属性中会引用该名称)
//	name = "${custom.security.name:Authenticate}",
//	// 指定认证类型为oauth2
//	type = SecuritySchemeType.OAUTH2,
//	// 设置认证流程
//	flows = @io.swagger.v3.oas.annotations.security.OAuthFlows(
//		// 设置授权码模式
//		authorizationCode = @io.swagger.v3.oas.annotations.security.OAuthFlow(
//			// 获取token地址
//			tokenUrl = "${custom.security.token-url:'http://kwqqr48rgo.cdhttp.cn/oauth2/token'}",
//			// 授权申请地址
//			authorizationUrl = "${custom.security.authorization-url:'http://kwqqr48rgo.cdhttp.cn/oauth2/authorize'}",
//			// oauth2的申请的scope(需要在OAuth2客户端中存在)
//			scopes = {
//				@OAuthScope(name = "openid", description = "OpenId登录"),
//				@OAuthScope(name = "profile", description = "获取用户信息"),
//				@OAuthScope(name = "message.read", description = "读"),
//				@OAuthScope(name = "message.write", description = "写")
//			}
//		)
//	)
//)})
public class SpringdocAutoConfiguration implements InitializingBean {

	//@Value("${spring.cloud.client.ip-address}")
	//private String ip;

	@Value("${server.port:8080}")
	private int port;

	@Value("${spring.mvc.servlet.path:/}")
	private String servletPath;

	private final SpringdocProperties properties;

	public SpringdocAutoConfiguration(SpringdocProperties properties) {
		this.properties = properties;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		LogUtils.started(SpringdocAutoConfiguration.class, StarterName.SPRINGDOC_STARTER);
	}

	@Bean
	public GroupedOpenApi groupedOpenApi() {
		return GroupedOpenApi.builder()
			.group(properties.getGroup())
			.pathsToMatch(properties.getPathsToMatch())
			.pathsToExclude(properties.getPathsToExclude())
			.packagesToScan(properties.getPackagesToScan())
			// .packagesToExclude(properties.getPackagesToExclude())
			// .addOpenApiCustomizer(openApiCustomizer())
			.build();
	}

	@Bean
	public OpenApiCustomizer openApiCustomizer() {
		return openApi -> {
			final Paths paths = openApi.getPaths();

			Paths newPaths = new Paths();
			paths.keySet().forEach(e -> newPaths.put("/api/v" + properties.getVersion() + e, paths.get(e)));
			openApi.setPaths(newPaths);

			openApi.getPaths().values().stream()
				.flatMap(pathItem -> pathItem.readOperations().stream())
				.forEach(operation -> {
				});

			if (CollUtil.isEmpty(properties.getTags())) {
				openApi.setTags(properties.getTags());

				openApi.setTags(openApi.getTags().stream()
					.sorted(Comparator.comparing(tag -> StringUtils.stripAccents(tag.getName())))
					.collect(Collectors.toList()));
			}
		};
	}

	@Bean
	public OpenAPI openApi() {
		// 组件
		Components components = new Components();

		Map securitySchemes = properties.getSecuritySchemes();
		if (CollUtil.isEmpty(securitySchemes)) {
			// 安全认证组件

			components.addSecuritySchemes(
				"token",
				new SecurityScheme()
					.name("token")
					.description("token")
					.type(SecurityScheme.Type.HTTP)
					.in(In.HEADER)
					.scheme("bearer"));

			// components.addSecuritySchemes("bearer",
			//	new SecurityScheme()
			//		.name(HttpHeaders.AUTHORIZATION)
			//		.type(SecurityScheme.Type.HTTP)
			//		.in(In.HEADER)
			//		.scheme("bearer")
			//		.bearerFormat("JWT")
			// );
			// components.addSecuritySchemes("taotao_token",
			//	new SecurityScheme()
			//		.name("TAOTAO_CLOUD_AUTH")
			//		.type(Type.OAUTH2)
			//		.in(In.HEADER)
			//		.scheme("bearer")
			//		.bearerFormat("JWT")
			//		.flows(password)
			//		.flows(clientCredentials)
			// );

		} else {
			securitySchemes.forEach(components::addSecuritySchemes);
		}

		Map headers = properties.getHeaders();
		if (CollUtil.isEmpty(headers)) {
			// 添加全局header
			components.addHeaders(
				"ttc-request-version-header",
				new Header().description("版本号").schema(new StringSchema()));
			components.addHeaders(
				"ttc-request-weight-header",
				new Header().description("权重").schema(new IntegerSchema()));
		} else {
			headers.forEach(components::addHeaders);
		}

		List servers = properties.getServers();
		if (CollUtil.isEmpty(servers)) {
			Server s1 = new Server();
			s1.setUrl("http://" + IpUtils.getLocalIp() + ":" + port + "" + servletPath);
			s1.setDescription("本地地址");
			servers.add(s1);
			Server s2 = new Server();
			s2.setUrl("http://dev.taotaocloud.com/");
			s2.setDescription("测试环境地址");
			servers.add(s2);
			Server s3 = new Server();
			s3.setUrl("https://pre.taotaocloud.com/");
			s3.setDescription("预上线环境地址");
			servers.add(s3);
			Server s4 = new Server();
			s4.setUrl("https://pro.taotaocloud.com/");
			s4.setDescription("生产环境地址");
			servers.add(s4);
		}

		Contact contact = new Contact()
			.name("shuigedeng")
			.email("[email protected]")
			.url("https://github.com/shuigedeng/taotao-cloud-project");
		License license = new License()
			.name("Apache 2.0")
			.url("https://github.com/shuigedeng/taotao-cloud-project/blob/master/LICENSE.txt");

		//基础信息
		Info info = new Info()
			.title(properties.getTitle())
			.description(properties.getDescription())
			.version(properties.getVersion())
			.contact(Objects.isNull(properties.getContact()) ? contact : properties.getContact())
			.termsOfService(properties.getTermsOfService())
			.license(Objects.isNull(properties.getLicense()) ? license : properties.getLicense());

		ExternalDocumentation externalDocumentation = new ExternalDocumentation()
			.description(properties.getExternalDescription())
			.url(properties.getExternalUrl());

		//第二种.集成OAuth2登录认证
		// 安全认证组件
		SecurityScheme securityScheme = new SecurityScheme();
		// 创建一个oauth认证流程
		OAuthFlows oAuthFlows = new OAuthFlows();
		// 设置OAuth2流程中认证服务的基本信息
		OAuthFlow oAuthFlow = new OAuthFlow()
			// 授权申请地址
			.authorizationUrl("http://kwqqr48rgo.cdhttp.cn/oauth2/authorize")
			// 获取token地址
			.tokenUrl("http://kwqqr48rgo.cdhttp.cn/oauth2/token")
			.scopes(new Scopes()
				.addString("openid", "OpenId登录")
				.addString("profile", "获取用户信息")
				.addString("message.read", "读")
				.addString("message.write", "写")
			);
		// 使用授权码模式
		oAuthFlows.authorizationCode(oAuthFlow);
		// OAuth2流程
		securityScheme.flows(oAuthFlows)
			.type(SecurityScheme.Type.OAUTH2);
		// 安全认证名
		String securityName = "Authenticate";
		// 将认证配置加入组件中
		components.addSecuritySchemes(securityName, securityScheme);
		SecurityRequirement securityRequirement = new SecurityRequirement();
		// 将安全认证和swagger-ui关联起来
		securityRequirement.addList(securityName);

		return new OpenAPI()
			.components(components)
			.openapi(properties.getOpenapi())
			.info(info)
			.servers(servers)
			.externalDocs(externalDocumentation)
			// 添加请求时携带OAuth2规范的请求头(通过OAuth2流程获取token后发请求时会自动携带Authorization请求头)
			.addSecurityItem(securityRequirement);

	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy