You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 7 API添加[Authorize]后出现No authenticationScheme指定错误求助

问题原因

你在.NET7中同时存在Program.cs和Startup.cs,但.NET7默认采用顶级语句的启动模式,没有自动加载Startup.cs中的配置。你的JWT认证逻辑写在Startup.cs的ConfigureServices里,但这些代码根本没被执行,导致应用服务容器中缺少认证方案的配置,触发了"No authenticationScheme was specified..."错误。

解决方案

你可以选择以下两种方式修复:


方式一:将Startup配置合并到Program.cs

直接把Startup.cs中的服务配置和中间件逻辑迁移到Program.cs,这是.NET7推荐的写法:

修改后的Program.cs完整代码:

using System.Text;
using System.Globalization;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Hangfire;
using Hangfire.SqlServer;

var builder = WebApplication.CreateBuilder(args);

// 从Startup迁移的服务配置
builder.Services.AddResponseCompression();
builder.Services.AddCors();
builder.Services.AddControllers();

// 添加DbContext
builder.Services.AddDbContext<VisionContexto>(
    opt => opt.UseSqlServer(builder.Configuration.GetConnectionString("VisionContexto"),
    b => b.MigrationsAssembly("Vision.Dados")));

// JWT认证配置
var key = Encoding.ASCII.GetBytes(builder.Configuration.GetValue<string>("Configuracoes:ChaveSecreta"));
builder.Services.AddAuthentication(x =>
{
    x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
    x.RequireHttpsMetadata = false;
    x.SaveToken = true;
    x.IncludeErrorDetails = true;
    x.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(key),
        ValidateLifetime = true,
        ValidateIssuer = false,
        ValidateAudience = false,
        ClockSkew = TimeSpan.Zero
    };
});

// API版本控制
builder.Services.AddApiVersioning(options =>
{
    options.ReportApiVersions = true;
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.DefaultApiVersion = ApiVersion.Default;
    options.ApiVersionReader = ApiVersionReader.Combine(new MediaTypeApiVersionReader("x-api-version"), new HeaderApiVersionReader("x-api-version"));
});
builder.Services.AddVersionedApiExplorer(options =>
{
    options.GroupNameFormat = "'v'VV";
    options.SubstituteApiVersionInUrl = true;
});

// Swagger配置
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
    c.OperationFilter<SwaggerDefaultValues>();
    c.SwaggerDoc("v1",
        new Microsoft.OpenApi.Models.OpenApiInfo
        {
            Title = "Vision API",
            Version = "v1",
            Description = "Vision Web API",
            Contact = new Microsoft.OpenApi.Models.OpenApiContact
            {
                Name = "Vision",
                Email = "app@prodadosinformatica.com.br",
                Url = new Uri("https://www.prodadosinformatica.com.br")
            }
        });
    c.DocInclusionPredicate((_, api) => !string.IsNullOrWhiteSpace(api.GroupName));
    c.TagActionsBy(api => api.GroupName);
    string caminhoAplicacao = AppContext.BaseDirectory;
    string nomeAplicacao = System.Reflection.Assembly.GetEntryAssembly().GetName().Name;
    string caminhoXmlDoc = Path.Combine(caminhoAplicacao, $"{nomeAplicacao}.xml");
    c.IncludeXmlComments(caminhoXmlDoc);
});
builder.Services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerGenOptions>();

// Hangfire配置
builder.Services.AddHangfire(configuration => configuration
   .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
   .UseSimpleAssemblyNameTypeSerializer()
   .UseRecommendedSerializerSettings()
   .UseSqlServerStorage(builder.Configuration.GetConnectionString("VisionContexto"),
   new SqlServerStorageOptions
   {
       CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
       SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
       QueuePollInterval = TimeSpan.Zero,
       UseRecommendedIsolationLevel = true,
       DisableGlobalLocks = true
   }));
builder.Services.AddHangfireServer();

// 其他配置
builder.Services.Configure<PasswordHasherOptions>(options => options.CompatibilityMode = PasswordHasherCompatibilityMode.IdentityV2);
builder.Services.AddOptions();
builder.Services.Configure<Configuracoes.Configuracoes>(builder.Configuration.GetSection("Configuracoes"));

// 本地化配置
builder.Services.Configure<RequestLocalizationOptions>(
  options =>
  {
      var supportedCultures = new List<CultureInfo>
          {
                new CultureInfo("pt-BR"),
          };

      options.DefaultRequestCulture = new RequestCulture(culture: "pt-BR", uiCulture: "pt-BR");
      options.SupportedCultures = supportedCultures;
      options.SupportedUICultures = supportedCultures;
  });
Thread.CurrentThread.CurrentCulture = new CultureInfo("pt-BR");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("pt-BR");

// 日志配置
builder.Logging.AddDbLogger(options =>
{
    builder.Configuration.GetSection("Logging")
    .GetSection("Log").GetSection("Options").Bind(options);
});

var app = builder.Build();

// 中间件配置(从Startup迁移)
if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
app.UseSwagger();
app.UseSwaggerUI(options =>
{
    var provider = app.Services.GetRequiredService<IApiVersionDescriptionProvider>();
    foreach (var description in provider.ApiVersionDescriptions)
    {
        options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json",
            description.GroupName.ToUpperInvariant());
    }
    options.RoutePrefix = string.Empty;
});

app.UseResponseCompression();
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(x => x
  .AllowAnyOrigin()
  .AllowAnyMethod()
  .AllowAnyHeader());
app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();
app.Run();

方式二:在Program.cs中显式使用Startup类

如果你想保留Startup.cs,只需在Program.cs中添加一行代码,让应用加载Startup的配置:

修改后的Program.cs:

var builder = WebApplication.CreateBuilder(args);

// 显式指定使用Startup类
builder.WebHost.UseStartup<Startup>();

var app = builder.Build();

app.Run();

注意:这种方式下,Program.cs中原来的服务配置和中间件代码需要删除,避免和Startup.cs中的配置重复冲突。

关键注意点
  • 中间件顺序必须正确:UseCors要放在UseAuthentication和UseAuthorization之前,否则CORS配置不会生效。
  • 确保appsettings.json中存在Configuracoes:ChaveSecreta配置项,且值是有效的密钥字符串。

内容的提问来源于stack exchange,提问作者Saulo Pacífico

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 17:44:51