using Tiobon.Core.Common; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Models; using Serilog; using Swashbuckle.AspNetCore.Filters; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; using static Tiobon.Core.Extensions.CustomApiVersion; using Microsoft.AspNetCore.Builder; using Swashbuckle.AspNetCore.SwaggerUI; using Microsoft.Extensions.Options; namespace Tiobon.Core.Extensions { /// /// Swagger 启动服务 /// public static class SwaggerSetup { public static void AddSwaggerSetup(this IServiceCollection services) { if (services == null) throw new ArgumentNullException(nameof(services)); var basePath = AppContext.BaseDirectory; services.AddSwaggerGen(c => { ApiInfos.ForEach(x => { c.SwaggerDoc(x.UrlPrefix, x.OpenApiInfo); c.OrderActionsBy(o => o.RelativePath); }); c.UseInlineDefinitionsForEnums(); // 开启加权小锁 c.OperationFilter(); c.OperationFilter(); // 在header中添加token,传递到后台 c.OperationFilter(); // API注释所需XML文件 try { c.IncludeXmlComments(Path.Combine(basePath, "Tiobon.Core.xml"), true); c.IncludeXmlComments(Path.Combine(basePath, "Tiobon.Core.Model.xml"), true); } catch (Exception ex) { Log.Error("Tiobon.Core.xml和Tiobon.Core.Model.xml 丢失,请检查并拷贝。\n" + ex.Message); } c.MapType(() => new OpenApiSchema { Type = "string", Format = "string" }); // ids4和jwt切换 if (Permissions.IsUseIds4) { //接入identityserver4 c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme { Type = SecuritySchemeType.OAuth2, Flows = new OpenApiOAuthFlows { Implicit = new OpenApiOAuthFlow { AuthorizationUrl = new Uri($"{AppSettings.app(new string[] { "Startup", "IdentityServer4", "AuthorizationUrl" })}/connect/authorize"), Scopes = new Dictionary { { "Tiobon.core.api", "ApiResource id" } } } } }); } else { c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Name = "Authorization", Type = SecuritySchemeType.ApiKey, BearerFormat = "JWT", In = ParameterLocation.Header, Scheme = "Bearer", Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)\"", }); } c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } }, new List() } }); }); services.AddSwaggerGenNewtonsoftSupport(); } public static void UseSwaggerMiddle(this IApplicationBuilder app, Func streamHtml) { if (app == null) throw new ArgumentNullException(nameof(app)); SwaggerBuilderExtensions.UseSwagger(app); app.UseSwaggerUI(options => { // 遍历分组信息,生成Json ApiInfos.ForEach(x => { options.SwaggerEndpoint($"/swagger/{x.UrlPrefix}/swagger.json", x.Name); }); // 模型的默认扩展深度,设置为 -1 完全隐藏模型 options.DefaultModelsExpandDepth(-1); // API文档仅展开标记 options.DocExpansion(DocExpansion.List); // API前缀设置为空 options.RoutePrefix = string.Empty; // API页面Title options.DocumentTitle = "接口文档"; if (streamHtml.Invoke() == null) { var msg = "index.html的属性,必须设置为嵌入的资源"; Log.Error(msg); throw new Exception(msg); } options.IndexStream = streamHtml; options.DocExpansion(DocExpansion.None); //->修改界面打开时自动折叠 if (Permissions.IsUseIds4) { options.OAuthClientId("Tiobonadminjs"); } //增加令牌本地缓存 reload不会丢失 options.ConfigObject.AdditionalItems.Add("persistAuthorization", "true"); // 路径配置,设置为空,表示直接在根域名(localhost:8001)访问该文件,注意localhost:8001/swagger是访问不到的,去launchSettings.json把launchUrl去掉,如果你想换一个路径,直接写名字即可,比如直接写c.RoutePrefix = "doc"; options.RoutePrefix = ""; }); } /// /// 当前API版本 /// private static readonly string version = $"V1.0"; /// /// Swagger分组信息,将进行遍历使用 /// private static readonly List ApiInfos = new List() { new SwaggerApiInfo { UrlPrefix = Grouping.GroupName_Auth, Name = "认证授权", OpenApiInfo = new OpenApiInfo { Version = version, Title = "认证授权", Description = "登录/注销", } }, new SwaggerApiInfo { UrlPrefix = Grouping.GroupName_System, Name = "系统模块", OpenApiInfo = new OpenApiInfo { Version = version, Title = "系统模块", Description = "用户/角色/权限...", } }, new SwaggerApiInfo { UrlPrefix = Grouping.GroupName_Assistant, Name = "工具模块", OpenApiInfo = new OpenApiInfo { Version = version, Title = "工具模块", Description = "自助测量程序/中央站...", } }, new SwaggerApiInfo { UrlPrefix = Grouping.GroupName_Other, Name = "其他模块", OpenApiInfo = new OpenApiInfo { Version = version, Title = "其他模块", Description = "其他...", } }, new SwaggerApiInfo { UrlPrefix = Grouping.GroupName_Ghre, Name = "培训模块", OpenApiInfo = new OpenApiInfo { Version = version, Title = "培训模块", Description = "培训模块..." } }, new SwaggerApiInfo { UrlPrefix = Grouping.GroupName_Ghra, Name = "Ghra模块", OpenApiInfo = new OpenApiInfo { Version = version, Title = "Ghra模块", Description = "Ghra...", } } }; private class SwaggerApiInfo { /// /// URL前缀 /// public string UrlPrefix { get; set; } /// /// 名称 /// public string Name { get; set; } /// /// OpenApiInfo /// public OpenApiInfo OpenApiInfo { get; set; } } /// /// swagger分组 /// public static class Grouping { /// /// 系统 /// public const string GroupName_System = "system"; /// /// 系统 /// public const string GroupName_Ghrs = "system"; /// /// 认证授权 /// public const string GroupName_Auth = "auth"; /// /// 其他 /// public const string GroupName_Other = "other"; /// /// Ghra /// public const string GroupName_Ghra = "ghra"; /// /// ghro /// public const string GroupName_Ghro = "ghro"; /// /// 辅助工具 /// public const string GroupName_Assistant = "assistant"; /// /// 培训模块 /// public const string GroupName_Ghre = " ghre"; } } /// /// 自定义版本 /// public class CustomApiVersion { /// /// Api接口版本 自定义 /// public enum ApiVersions { /// /// Ghra 版本 /// Ghra = 0, /// /// V1 版本 /// V1 = 1, /// /// V2 版本 /// V2 = 2, } } }