如何让Swagger/Swashbuckle使用现有System.Security.Claims.ClaimsPrincipal类型
System.Security.Claims.ClaimsPrincipal类型而非生成自定义版本的问题 我尝试让Swagger使用现有的System.Security.Claims.ClaimsPrincipal类型,而非生成该类型的自定义版本。通过谷歌、ChatGPT等方式查找解决方案均无成效,仅有的少量线索指向通过生成器参数配置的可能方案,但我认为应该可以通过代码实现。
当前代码如下:
services.Configure<SwaggerGenOptions>(options => { options.SchemaFilter<ClaimsPrincipalFilter>(); ... } public class ClaimsPrincipalFilter : ISchemaFilter { private const string existingNamespace = "System.Security.Claims"; public void Apply(OpenApiSchema schema, SchemaFilterContext context) { if (context.Type != typeof(ClaimsPrincipal)) return; schema.Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = $"{nameof(ClaimsPrincipal)}, {existingNamespace}" }; } }
运行后出现错误:
Resolver error at paths./v1/User.get.responses.200.content.text/json.schema.$ref
Could not resolve reference: Could not resolve pointer: /components/schemas/ClaimsPrincipal, System.Security.Claims does not exist in document.
我的需求是直接传递原生System.Security.Claims.ClaimsPrincipal类型的User对象,无需在另一端进行映射或使用“JSON序列化/反序列化”的临时方法。请问我遗漏了什么?
编辑:
我尝试调整Id的设置方式:
schema.Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "System.Security.Claims.ClaimsPrincipal" };
这消除了Swagger UI中的错误,但我的端点:
[HttpGet] [ProducesResponseType(typeof(ClaimsPrincipal), StatusCodes.Status200OK)] public IActionResult GetCurrentUser() => Ok(User);
不再返回结果,且端点上的断点从未触发。Swagger UI调用该端点后的响应如下:
content-length: 0 date: Fri,02 Jun 2023 15:09:00 GMT server: Kestrel x-correlation-id: 0HMR3FD1SBL9O:00000009
更糟的是,Swagger仍在错误的命名空间下生成了新模型:
MyNamspace.Service.Client.v1.Models.ClaimsPrincipal
这感觉是倒退了一步。
目前我在另一端使用以下映射方法来推进开发:
public static ClaimsPrincipal AsPrincipal(this MyNamspace.Service.Client.v1.Models.ClaimsPrincipal user) { if (user?.Claims == null || !user.Claims.Any()) return null; var claims = user.Claims.Select(x => new Claim(x.Type, x.Value)); return new ClaimsPrincipal(new ClaimsIdentity(claims)); }
另外,由于存在序列化相关的复杂问题,无论如何都需要使用DTO,之前的尝试其实没有意义。
内容的提问来源于stack exchange,提问作者Serj Sagan

