资讯中心

从 .NET 8 升到 .NET 10,我的 Swagger JWT 认证代码“编译不过“了

📅 2026/7/26 5:38:48
从 .NET 8 升到 .NET 10,我的 Swagger JWT 认证代码“编译不过“了
一、问题是什么把项目从 ASP.NET Core 8.0 升级到 10.0同时把Swashbuckle.AspNetCore从 6.x/7.x 升级到 10.x 之后原本在 .NET 8 下运行了很久、配置 Swagger JWT 认证的代码突然编译报错// .NET 8 时代的写法升级后编译报错builder.Services.AddSwaggerGen(options{options.AddSecurityDefinition(Bearer,newOpenApiSecurityScheme(){NameAuthorization,TypeSecuritySchemeType.ApiKey,InParameterLocation.Header,SchemeBearer,BearerFormatJWT,Description请输入Bearer token,});// 报错点AddSecurityRequirement 的参数类型不匹配options.AddSecurityRequirement(newOpenApiSecurityRequirement(){{newOpenApiSecurityScheme{ReferencenewOpenApiReference(){TypeReferenceType.SecurityScheme,IdBearer},SchemeBearer,NameBearer,InParameterLocation.Header,},newListstring()}});});编译器给出的错误是实参类型 “Microsoft.OpenApi.OpenApiSecurityRequirement” 不可分配给形参类型 “System.FuncMicrosoft.OpenApi.OpenApiDocument,Microsoft.OpenApi.OpenApiSecurityRequirement”翻译过来就是一句话AddSecurityRequirement方法要的参数类型变了——以前直接传一个OpenApiSecurityRequirement对象就行现在它要的是一个委托一个接收OpenApiDocument、返回OpenApiSecurityRequirement的函数。二、为什么会变这不是 Swashbuckle 团队随手改的一个签名根子在更底层的依赖上。Swashbuckle.AspNetCore 从诞生起就没有自己造 OpenAPI 对象模型的轮子而是直接依赖并暴露微软官方的Microsoft.OpenApi也就是 OpenAPI.NET库里的类型比如OpenApiSecurityScheme、OpenApiSecurityRequirement这些都是直接从Microsoft.OpenApi命名空间里透传出来给使用者的。而从 ASP.NET Core 10 开始如果使用 Microsoft.AspNetCore.OpenApi 这个 NuGet 包就依赖 Microsoft.OpenApi v2 以上的版本。Swashbuckle.AspNetCore 10.x 为了能在 .NET 10 上顺畅工作也同步把底层依赖升级到了Microsoft.OpenApiv2。问题就出在这次大版本升级上——Swashbuckle.AspNetCore 9.x 依赖的是 OpenAPI.NET 1.x那个版本里 OpenApiSecurityScheme 还带着 Reference 属性能直接引用一个已定义的安全方案而 OpenAPI.NET 2.0 引入了破坏性的 API 变更Reference这种先定义、再引用的老写法被去掉了取而代之的是一套新的引用类型体系同时AddSecurityRequirement的方法签名也顺势改成了接收委托的形式方便你在委托里拿到完整的OpenApiDocument上下文去动态构建安全要求。一句话总结这次升级的因果链ASP.NET Core 10 内置 OpenAPI 能力依赖 Microsoft.OpenApi v2 → Swashbuckle.AspNetCore 10.x 跟进依赖 Microsoft.OpenApi v2 → OpenAPI.NET v2 是破坏性升级砍掉了OpenApiSecurityScheme.Reference→ 旧的 JWT 认证配置代码全部编译不过。如果你在 GitHub 上翻 Swashbuckle 的 issue 区会发现这不是个例从 401 未授权到编译报错升级到 .NET 10 后 AddSecurityRequirement 编译失败、即便改对了签名 [Authorize] 接口依然返回 401 的情况都有不少人踩过坑。三、怎么解决解决思路就是照着新签名走把原来直接传对象改成传一个委托把原来靠Reference属性引用安全方案改成用新的OpenApiSecuritySchemeReference类型直接构造引用。builder.Services.AddSwaggerGen(options{// 定义部分基本不变只是去掉了 new OpenApiSecurityScheme() 后面多余的括号写法差异options.AddSecurityDefinition(Bearer,newOpenApiSecurityScheme{NameAuthorization,InParameterLocation.Header,TypeSecuritySchemeType.ApiKey,SchemeBearer,BearerFormatJWT,Description请输入Bearer token});// 关键变化AddSecurityRequirement 现在接收一个委托// document 参数就是当前正在生成的 OpenApiDocument// 用它构造出的 OpenApiSecuritySchemeReference 能正确关联到上面定义的 Bearer 安全方案options.AddSecurityRequirement(documentnewOpenApiSecurityRequirement(){{newOpenApiSecuritySchemeReference(Bearer,document,null){DescriptionJWT授权,},newListstring()}});});改动其实只有两处AddSecurityRequirement的参数从对象变成了FuncOpenApiDocument, OpenApiSecurityRequirement。所以外面要包一层document new OpenApiSecurityRequirement() { ... }document参数由 Swashbuckle 在生成文档时自动传入不需要我们手动构造。不再用new OpenApiSecurityScheme { Reference ... }这种裸对象 Reference 属性的方式引用已定义的安全方案改用OpenApiSecuritySchemeReference(Bearer, document, null)直接构造一个引用类型第一个参数是AddSecurityDefinition时注册的方案名这里要保证大小写完全一致否则引用会失效页面上锁头图标点了也没反应第二个参数是当前文档第三个参数是可选的描述覆盖传null即可。改完之后重新编译、启动项目Swagger UI 右上角的 “Authorize” 按钮依然能正常弹出输入框粘贴Bearer xxx之后所有带[Authorize]的接口都能正常带上认证头行为和 .NET 8 时代完全一致。四、给同样在升级路上的你提个醒如果你的项目里除了 JWT 认证配置还用到了 Swashbuckle 的IDocumentFilter、IOperationFilter里手动构造OpenApiSecurityScheme、引用其他 Schema 等写法升级到 10.x 时也大概率会踩到同样的坑——本质都是Microsoft.OpenApiv1 到 v2 的破坏性变更。建议的排查顺序是编译报错先别急着改代码看清楚报错信息里到底是类型不匹配还是成员不存在前者多半是方法签名变了比如这次的AddSecurityRequirement后者多半是属性被移除了比如这次的Reference。官方有专门的 v10 迁移文档遇到编译不过的地方先去对照一遍能省掉很多试错时间。升级路径上如果条件允许先升到 Swashbuckle.AspNetCore 9.0.6 再升 10.x官方也建议这样过渡能减少一次性踩坑的数量。技术栈的版本号往前走一位看着只是小版本变化但只要底层依赖发生了破坏性升级暴露在外层的 API 就都得跟着变。遇到这种编译不过的报错与其猜不如先搞清楚它到底依赖了谁、那个谁又发生了什么变化——这次的排查思路希望对同样在做 .NET 10 升级的你有用。