我有一个用于多个 api 版本控制的 asp.net core 6 项目设置。但是,当我打开 nswager api 文档时。右侧的授权按钮根本不显示。我不确定我错过了什么。
下面是我的代码片段:
public static IServiceCollection AddSwaggerTest(this IServiceCollection serviceCollection, string apiName)
{
serviceCollection.AddApiVersioning(opt =>
{
opt.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(1, 0);
opt.AssumeDefaultVersionWhenUnspecified = true;
opt.ReportApiVersions = true;
opt.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader(),
new HeaderApiVersionReader("x-api-version"),
new MediaTypeApiVersionReader("x-api-version"));
})
.AddVersionedApiExplorer(setup =>
{
setup.GroupNameFormat = "'v'VVV";
setup.SubstituteApiVersionInUrl = true;
})
.AddSwaggerGen(option =>
{
option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
In = ParameterLocation.Header,
Description = "Please enter a valid token",
Name = "Authorization",
Type = SecuritySchemeType.Http,
BearerFormat = "JWT",
Scheme = "Bearer"
});
option.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type=ReferenceType.SecurityScheme,
Id="Bearer"
}
},
new string[]{}
}
});
option.EnableAnnotations();
option.CustomSchemaIds(x => x.FullName);
var provider = serviceCollection.BuildServiceProvider().GetRequiredService<IApiVersionDescriptionProvider>();
foreach (var description in provider.ApiVersionDescriptions)
{
var xmlPath = Path.Combine(AppContext.BaseDirectory, $"{apiName}.xml");
if (File.Exists(xmlPath))
{
option.IncludeXmlComments(xmlPath);
}
}
})
.AddSwaggerDocuments(apiName);
return serviceCollection;
}
private static IServiceCollection AddSwaggerDocuments(this IServiceCollection serviceCollection, string swaggerApiName)
{
var provider = serviceCollection.BuildServiceProvider().GetRequiredService<IApiVersionDescriptionProvider>();
foreach (var description in provider.ApiVersionDescriptions)
{
serviceCollection.AddSwaggerDocument(config =>
{
config.DocumentName = description.GroupName.ToLower();
config.PostProcess = document =>
{
document.Info.Version = description.GroupName.ToLower();
document.Info.Title = swaggerApiName;
document.Info.Description = description.IsDeprecated
? "This Api version has been depreciated"
: "A versioned TTC Fas Rest API";
};
config.ApiGroupNames = new[] { description.GroupName.ToLower() };
});
}
return serviceCollection;
}
所以在我的 Progarm.cs 中。我会有这样的东西:
\\ Something ...
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerTest("test");
builder.Services.AddAuthentication(authOptions =>
{
authOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
authOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(jwtOptions =>
{
jwtOptions.SaveToken = true;
jwtOptions.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = true,
ValidateIssuer = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "Test",
ValidAudience = "https://localhost:7117",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("superSecretKey@2410"))
};
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseOpenApi();
app.UseSwaggerUi3(config => config.DocExpansion = "list");
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
我的 v1 控制器:
[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching", "v1"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[Authorize]
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
v2 控制器:
[ApiController]
[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching", "v2"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[Authorize]
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
我在 v1 和 v2 中都有登录控制器。
================================================= ==========
我自己找到了解决办法。我没有使用
UseOpenApi
和
UseSwaggerUi3
不再来自 Nswag.AspnetCore
包,所以我决定删除这个包并使用 UseSwagger
和 UseSwaggerUI
来自
Swashbuckle.AspNetCore
和Swashbuckle.AspNetCore.SwaggerUI
AddSwaggerTest
函数和控制器中的所有内容都是相同的。
这是我让它工作的方法:
\\ something is running
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerTest("test");
builder.Services.AddAuthentication(authOptions =>
{
authOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
authOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(jwtOptions =>
{
jwtOptions.SaveToken = true;
jwtOptions.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = true,
ValidateIssuer = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "Test",
ValidAudience = "https://localhost:7117",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("superSecretKey@2410"))
};
});
var app = builder.Build();
var apiVersionDescriptionProvider = app.Services.GetRequiredService<IApiVersionDescriptionProvider>();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions)
{
c.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json",
description.GroupName.ToUpperInvariant());
}
});
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
既然你使用了
AddSecurityDefinition
和AddSecurityRequirement
,我们应该改变中间件的顺序。
像下面这样更改您的代码:
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseOpenApi();
app.UseSwaggerUi3(config => config.DocExpansion = "list");
}
app.MapControllers();
app.Run();