云南网站制作一条龙,手机端网页模板免费,天津网站建设培训学校,网站建设需要什么设备前言当需要在生产环境中提供 Swagger UI 时#xff0c;我们可以通过身份验证#xff0c;控制只有授权用户才能访问 Swagger UI 页面。但是我们希望更进一步#xff0c;每个用户只能看到授权给他的终结点#xff0c;而不会暴露其他未授权终结点信息。比如#xff0c; API 提…前言当需要在生产环境中提供 Swagger UI 时我们可以通过身份验证控制只有授权用户才能访问 Swagger UI 页面。但是我们希望更进一步每个用户只能看到授权给他的终结点而不会暴露其他未授权终结点信息。比如 API 提供了方法 A 和 方法 B而对于用户 zhangsan 来说他在 Swagger UI 页面只能看到方法 A 的说明而不会知道方法 B 的存在。思路Swagger UI 页面展示的数据来源其实是/swagger/v1/swagger.json文件app.UseSwaggerUI(c c.SwaggerEndpoint(/swagger/v1/swagger.json, WebApplication1 v1));而swagger.json的格式是遵循 OpenAPI 规范的。其中paths定义了 API 的所有终结点那么只需要保证swagger.json包含的paths仅定义了授权接口的终结点即可。虽然我们不能控制swagger.json文件的生成但是我们可以控制它如何输出到响应啊我们可以定义一个Middleware实现如下功能判断当前请求是否swagger.json如果是截获原始响应即swagger.json文件内容创建一个新的 json 文件遍历swagger.json所有 JSON 结点写入到新 json 文件中如果当前节点是paths节点下的子节点先判断子节点名称是否是授权终结点是则写入否则跳过将新 json 文件输出到响应中实现SwaggerEndpointsFilterMiddleware实现代码如下public class SwaggerEndpointsFilterMiddleware
{private readonly RequestDelegate _next;public SwaggerEndpointsFilterMiddleware(RequestDelegate next){_next next;}public async Task Invoke(HttpContext httpContext){if (httpContext.Request.Path.Value ! null httpContext.Request.Path.HasValue httpContext.Request.Path.Value.Contains(swagger.json, StringComparison.InvariantCultureIgnoreCase)){var originalStream httpContext.Response.Body;using (var memoryStream new MemoryStream()){//截获原始响应将响应内容写入 MemoryStreamhttpContext.Response.Body memoryStream;await _next(httpContext);//获取当前用户可访问的 Endpointsvar validEndpoints GetValidEndpoints(httpContext.Request);memoryStream.Position 0;using (var sr new StreamReader(memoryStream)){//将修改过的 json 写入响应 await originalStream.WriteAsync(CreateSwaggerJson(sr.ReadToEnd(), validEndpoints));}httpContext.Response.Body originalStream;return;}}await _next(httpContext);}
}关键代码在CreateSwaggerJson:private byte[] CreateSwaggerJson(string json, IEnumerablestring validEndpoints)
{using (var memoryStream new MemoryStream()){using (var utf8JsonWriter new Utf8JsonWriter(memoryStream)){using (var jsonDocument JsonDocument.Parse(json)){utf8JsonWriter.WriteStartObject();foreach (var element in jsonDocument.RootElement.EnumerateObject()){if (element.Name paths){utf8JsonWriter.WritePropertyName(element.Name);utf8JsonWriter.WriteStartObject();//遍历 paths 子节点检查 Endpoint 是否已授权foreach (var endpoint in element.Value.EnumerateObject()){if (validEndpoints.Contains(endpoint.Name)){endpoint.WriteTo(utf8JsonWriter);}}utf8JsonWriter.WriteEndObject();}else{element.WriteTo(utf8JsonWriter);}}utf8JsonWriter.WriteEndObject();}}return memoryStream.ToArray();}
}最后修改 Startup.cs:app.UseMiddlewareSwaggerEndpointsFilterMiddleware();app.UseSwagger();
app.UseSwaggerUI(c c.SwaggerEndpoint(/swagger/v1/swagger.json, WebApplication1 v1));结论今天我们通过 Middleware 拦截swagger.json的输出实现了 Swagger UI 仅为用户暴露已授权终结点。添加微信号【MyIO666】邀你加入技术交流群