.NET Core中如何控制Swagger文档的访问权限?
嘿,这个问题我之前帮好几个开发者处理过,在.NET Core里给Swagger文档加访问限制其实有几种很实用的方案,我给你一一拆解清楚:
方案1:仅在开发环境启用Swagger
如果你的Swagger文档只需要在开发/测试环境供团队内部查看,生产环境完全没必要暴露,那直接加个环境判断就够了,简单又安全:
var builder = WebApplication.CreateBuilder(args); // 先注册Swagger服务(不管环境都可以注册,只是中间件只在开发环境启用) builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // 只有开发环境才启用Swagger UI和JSON端点 if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); }); } // 其他中间件配置... app.UseHttpsRedirection(); app.MapControllers(); app.Run();
这样生产环境下,任何人访问/swagger路径都会直接返回404,完全隐藏Swagger的存在。
方案2:添加基本认证(Basic Authentication)
要是生产环境确实得让少数授权人员访问Swagger,那加个基础的账号密码验证就够了,不用搞复杂的认证系统。可以通过自定义中间件实现:
首先创建中间件类:
public class SwaggerBasicAuthMiddleware { private readonly RequestDelegate _next; private readonly IConfiguration _configuration; public SwaggerBasicAuthMiddleware(RequestDelegate next, IConfiguration configuration) { _next = next; _configuration = configuration; } public async Task InvokeAsync(HttpContext context) { // 只拦截Swagger相关的请求路径 if (context.Request.Path.StartsWithSegments("/swagger")) { string authHeader = context.Request.Headers["Authorization"]; if (authHeader != null && authHeader.StartsWith("Basic ")) { // 解码请求里的账号密码 var encodedCreds = authHeader.Split(' ', 2, StringSplitOptions.RemoveEmptyEntries)[1]?.Trim(); var decodedCreds = Encoding.UTF8.GetString(Convert.FromBase64String(encodedCreds)); var username = decodedCreds.Split(':', 2)[0]; var password = decodedCreds.Split(':', 2)[1]; // 从配置文件读取预设的合法账号密码(生产环境建议用Secret Manager或环境变量,别硬编码) var validUsername = _configuration["SwaggerAuth:Username"]; var validPassword = _configuration["SwaggerAuth:Password"]; if (username == validUsername && password == validPassword) { await _next(context); return; } } // 验证失败的话,返回401并提示需要认证 context.Response.Headers["WWW-Authenticate"] = "Basic"; context.Response.StatusCode = StatusCodes.Status401Unauthorized; } else { await _next(context); } } }
然后在Program.cs里注册这个中间件(注意要放在UseSwagger和UseSwaggerUI之前):
var builder = WebApplication.CreateBuilder(args); // 注册Swagger服务 builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // 注册Swagger基本认证中间件 app.UseMiddleware<SwaggerBasicAuthMiddleware>(); // 启用Swagger(现在加了认证,环境不限) app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); }); // 其他中间件配置... app.UseHttpsRedirection(); app.MapControllers(); app.Run();
最后在appsettings.json里配置账号密码:
{ "SwaggerAuth": { "Username": "admin", "Password": "YourStrongPassword123!" } }
方案3:基于现有身份认证系统的授权(比如JWT、Cookie)
如果你的API已经有成熟的身份认证机制(比如JWT令牌),可以直接给Swagger端点加授权限制,只允许特定角色/权限的用户访问:
先确保项目已经配置了身份认证(这里以JWT为例):
var builder = WebApplication.CreateBuilder(args); // 注册JWT认证 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])) }; }); // 定义授权策略:只允许Admin角色访问Swagger builder.Services.AddAuthorization(options => { options.AddPolicy("SwaggerAccess", policy => policy.RequireRole("Admin")); }); // 注册Swagger服务,并配置支持JWT认证(让Swagger UI可以输入令牌) builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" }); var securityScheme = new OpenApiSecurityScheme { Name = "Authorization", Type = SecuritySchemeType.Http, Scheme = "bearer", BearerFormat = "JWT", In = ParameterLocation.Header, Description = "JWT Authorization header using the Bearer scheme.", Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } }; c.AddSecurityDefinition("Bearer", securityScheme); c.AddSecurityRequirement(new OpenApiSecurityRequirement { { securityScheme, new string[] {} } }); }); var app = builder.Build(); // 启用认证和授权中间件(顺序别搞反:先认证后授权) app.UseAuthentication(); app.UseAuthorization(); // 启用Swagger app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); }); // 给Swagger的所有相关路径添加授权策略 app.Map("/swagger/v1/swagger.json", () => Results.Empty()) .RequireAuthorization("SwaggerAccess"); app.Map("/swagger", () => Results.Empty()) .RequireAuthorization("SwaggerAccess"); app.Map("/swagger/index.html", () => Results.Empty()) .RequireAuthorization("SwaggerAccess"); // 其他中间件配置... app.UseHttpsRedirection(); app.MapControllers().RequireAuthorization(); app.Run();
这样只有携带有效JWT令牌且拥有Admin角色的用户,才能访问Swagger文档。
内容的提问来源于stack exchange,提问作者Sayed Mohammad Hossain Rouhani
相关产品推荐
相关产品推荐

