簡體   English   中英

ASP.NET 升級到 3.0 后核心身份驗證中斷

[英]ASP.NET Core authentication broken after upgrade to 3.0

我有以下代碼,在 ASP.NET Core 2.2 下運行良好(已編輯以刪除特定於產品的命名)

public class Type1AuthenticationOptions : AuthenticationSchemeOptions {
   public string Secret { get; set; }
}

public class Type1AuthenticationHandler : AuthenticationHandler<Type1AuthenticationOptions> {

  public Type1AuthenticationHandler (IOptionsMonitor<Type1AuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
        : base(options, logger, encoder, clock)
    { }

    protected override Task<AuthenticateResult> HandleAuthenticateAsync() {
        ..
    }
}
// Repeat for Type2AuthenticationHandler

我的控制器是這樣注釋的:

[Route("api/thing")]
[Authorize(AuthenticationSchemes = "type1")]
public class ThingController : Controller {
   ...
}

[Route("api/thing2")]
[Authorize(AuthenticationSchemes = "type2")] // different way of authorizing for thing2
public class Thing2Controller : Controller {
   ...
}

如上所述,這一切都在 Asp.NET Core 2.2 以及之前的版本 2.1 和我認為 2.0 下運行良好。 關鍵部分(Configure 和 ConfigureServices 如下)

升級到 Asp.NET Core 3.0 后,代碼仍然可以編譯——所有的類、屬性和結構仍然存在,但是我的身份驗證處理程序永遠不會被調用。 如果我在Type1AuthenticationHandler的構造函數中放置一個斷點,它甚至不會被命中。

我的整個 Configure() 方法方法如下:

public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseAuthentication();
    app.UseAuthorization();

    app.UseRouting();

    app.UseEndpoints(endpoints => {
        endpoints.MapControllers();
    });

    if (env.IsDevelopment()) {
        app.UseDeveloperExceptionPage();
    }

    // Middleware to set the no-cache header value on ALL requests
    app.Use((context, next) => {
        context.Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue { NoCache = true };
        return next();
    });

我的 ConfigureServices 是

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

    services.AddControllers() // no views to be had here. Turn it off for security
        .AddNewtonsoftJson(opts => {
            opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            opts.SerializerSettings.Converters.Add(new StringEnumConverter { NamingStrategy = new CamelCaseNamingStrategy() });
        });

    services
        .AddAuthentication() // no default scheme, controllers must opt-in to authentication
        .AddScheme<Type1AuthenticationOptions, Type1AuthenticationHandler>("type1", o =>
        {
            o.Secret = Configuration.GetThing1Secret();
        })
        .AddScheme<Type2AuthenticationOptions, Type2AuthenticationHandler>("type2", o =>
        {
            o.Secret = Configuration.GetThing2Secret();
        });

    services.AddAuthorization();

    services.AddDbContext<DatabaseContext>(
        options => options.UseNpgsql(Configuration.GetDatabaseConnectionString()),
        ServiceLifetime.Transient);

    // Used for fire and forget jobs that need access to the context outside of the
    // the HTTP request that initiated the job
    services.AddTransient(provider =>
        new Func<DatabaseContext>(() => {
            var options = new DbContextOptionsBuilder<DatabaseContext>()
                .UseNpgsql(Configuration.GetDatabaseConnectionString())
                .UseLoggerFactory(provider.GetRequiredService<ILoggerFactory>())
                .Options;

            return new DatabaseContext(options);
        })
    );

    // make the configuration available to bits and pieces that may need it at runtime.
    // Note: Generally it's bad practice to use this, you should configure your thing here, and inject the configured-thing instead
    services.AddSingleton(Configuration);

    services.AddMemoryCache();

    // some more app-specific singleton services added but not relevant here
}

非常感謝任何幫助

PS 遠射,這是我的 csproj

<Project Sdk="Microsoft.NET.Sdk.Web">
    <PropertyGroup>
        <TargetFramework>netcoreapp3.0</TargetFramework>
        <UserSecretsId>99f957da-757d-4749-bd65-2b86753821a6</UserSecretsId>

        <!-- SonarQube needs this but it's otherwise irrelevant for dotnet core -->
        <ProjectGuid>{39054410-1375-4163-95e9-00f08b2efe2e}</ProjectGuid>
    </PropertyGroup>

    <PropertyGroup>
        <LangVersion>latest</LangVersion>
    </PropertyGroup>

    <ItemGroup>
        <Folder Include="wwwroot\" />
    </ItemGroup>
    <ItemGroup>
        <PackageReference Include="AWSSDK.S3" Version="3.3.104.31" />
        <PackageReference Include="AWSSDK.SimpleNotificationService" Version="3.3.101.68" />
        <PackageReference Include="AWSSDK.SimpleSystemsManagement" Version="3.3.106.12" />
        <PackageReference Include="Microsoft.AspNetCore.Hosting.WindowsServices" Version="3.0.0" />
        <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0" PrivateAssets="all">
        <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
        </PackageReference>
        <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.0" />
        <PackageReference Include="AWSSDK.Extensions.NETCore.Setup" Version="3.3.100.1" />
        <PackageReference Include="AWSSDK.SimpleEmail" Version="3.3.101.50" />
        <PackageReference Include="NLog" Version="4.6.7" />
        <PackageReference Include="NLog.Web.AspNetCore" Version="4.8.5" />
        <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.0.0-preview9" />
        <PackageReference Include="Portable.BouncyCastle" Version="1.8.5" />
        <PackageReference Include="System.IO.FileSystem.DriveInfo" Version="4.3.1" />
        <PackageReference Include="Microsoft.Extensions.Logging" Version="3.0.0" />
        <PackageReference Include="Microsoft.Extensions.Logging.Filter" Version="1.1.2" />
    </ItemGroup>
</Project>

在再次更詳細地查看遷移指南后,我注意到了這一點:

如果應用程序使用 AuthorizePage 或 [Authorize] 等身份驗證/授權功能,請在 UseRouting 之后(如果使用 CORS 中間件,則在 UseCors 之后)調用 UseAuthentication 和 UseAuthorization。

訣竅(遷移指南中沒有提到)似乎是 UseAuthentication/UseAuthorization 需要在 UseRouting 之后但在 UseEndpoints 之前。

這現在有效:

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints => {
   endpoints.MapControllers();
});

如果您在 UseEndpoints 之后進行 Auth 調用,則會收到有關缺少中間件的錯誤

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM