如何在集成测试中从服务中删除 AuthorizeAreaFolder 选项

How Can I remove AuthorizeAreaFolder option from service in integration test

我使用自定义 WebApplicationFactory 对我的 Razor Web 应用程序进行了集成测试:

public class CustomWebApplicationFactory<TStartup>
    : WebApplicationFactory<TStartup> where TStartup : class
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureServices(services =>
        {
            var descriptor = services.SingleOrDefault(
                d => d.ServiceType ==
                    typeof(DbContextOptions<GenericDbContext>));

            services.Remove(descriptor);


            services.AddDbContext<GenericDbContext>(options =>
            {
                options.UseInMemoryDatabase("InMemoryDbForTesting");
            });

            var sp = services.BuildServiceProvider();

            using var scope = sp.CreateScope();

            var scopedServices = scope.ServiceProvider;
            var db = scopedServices.GetRequiredService<GenericDbContext>();
            var logger = scopedServices
                .GetRequiredService<ILogger<CustomWebApplicationFactory<TStartup>>>();

            db.Database.EnsureCreated();

            try
            {
                Utilities.InitializeDbForTests(db);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "An error occurred seeding the " +
                    "database with test messages. Error: {Message}", ex.Message);
            }
        });
    }
}

在 TStartup 中,我传递了这个启动配置服务:

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

    //AzureADB2C
    services.AddAuthentication(sharedOptions =>
    {
        sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
    
    .AddAzureAdB2C(options => Configuration.Bind("Authentication:AzureAdB2C", options))
    .AddCookie(options =>
    {
        options.Cookie.SameSite = SameSiteMode.None;
        options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
        options.Cookie.IsEssential = true;
        //options.ExpireTimeSpan = TimeSpan.FromDays(365);
    });
    //AzureADB2C

    //Simple
    //services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme)
    //    .AddAzureADB2C(options => Configuration.Bind("Authentication:AzureAdB2C", options));


    services.Configure<CookiePolicyOptions>(options =>
    {
        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => false; // = context => true; //When set to true, TempData will not work unless the user opts in.
        options.MinimumSameSitePolicy = SameSiteMode.Unspecified; //If we dont do the hack for chrome/safari, this should be set to 'None'
        options.Secure = CookieSecurePolicy.Always;

        //Hack for Chrome/Safari. May not be needed in future
        options.OnAppendCookie = cookieContext =>
            CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
        options.OnDeleteCookie = cookieContext =>
           CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
    });

    services.AddRouting(options => {
        options.LowercaseUrls = true;
        //options.AppendTrailingSlash = false;
        });


 
    //Response Caching
    services.AddResponseCaching();

    //With conditional runtime compilation
    IMvcBuilder builder = services.AddRazorPages()
        .AddRazorPagesOptions(options =>
        {
            //Sitemap
            options.Conventions.AddAreaPageRoute("xxxxxx", "/xxxxxx", "xxxxxx.xml");
            options.Conventions.AddAreaPageRoute("xxxxxx", "/xxxxxx", "xxxxxx/xxxxxx.xml");
            options.Conventions.AddAreaPageRoute("xxxxxx", "/xxxxxx", "xxxxxx/xxxxxx.xml");
            options.Conventions.AddAreaPageRoute("xxxxxx", "/xxxxxx", "xxxxxx/xxxxxx.xml");
            options.Conventions.AddAreaPageRoute("xxxxxx", "/xxxxxx", "xxxxxx/xxxxxx.xml");
            options.Conventions.AddAreaPageRoute("xxxxxx", "/xxxxxx", "xxxxxx/xxxxxx.xml");
            options.Conventions.AddAreaPageRoute("xxxxxx", "/xxxxxx", "xxxxxx/xxxxxx.xml");



            options.Conventions.AuthorizeAreaFolder("xxxxxx", "/");
            options.Conventions.AuthorizeAreaFolder("xxxxxx", "/");
            options.Conventions.AuthorizeAreaFolder("xxxxxxx", "/", "xxxxx");
            //options.Conventions.AuthorizeAreaFolder("xxxx", "/");
            options.Conventions.AuthorizeAreaFolder("xxxxxx", "/");
            options.Conventions.AuthorizeAreaFolder("xxxxxx", "/");
            options.Conventions.AuthorizeAreaFolder("xxxxxx", "/");
            //options.Conventions.AuthorizeAreaFolder("xxxxx", "/");
            options.Conventions.AuthorizeAreaPage("xxxx", "/xxxxx");


            //password reset
            options.Conventions.AllowAnonymousToAreaPage("xxxxx", "/xxxxx");
            options.Conventions.AllowAnonymousToAreaPage("xxxxx", "/xxxx");

            //Checkout and 3DS pages
            options.Conventions.AllowAnonymousToAreaPage("xxxxx", "/xxxxx");


        });

    services.AddMemoryCache();

    //CACHE for tokens
    // Adds a default in-memory implementation of IDistributedCache.
    services.AddDistributedMemoryCache();
    //services.AddSession();

    services.AddSession(options =>
    {
        options.IdleTimeout = TimeSpan.FromHours(1);
        options.Cookie.HttpOnly = true;
        options.Cookie.IsEssential = true;
        options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
        options.Cookie.SameSite = SameSiteMode.Unspecified;// SameSiteMode.None;
        //options.IdleTimeout = TimeSpan.FromDays(365);
    });


    services.AddDbContext<IGenericDbContext, GenericDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("GenericDbConnection")));
}

就像我在自定义 WebApplicationFactory 中删除 dbContextOption 一样,我想删除 AuthorizeAreaFolder 或覆盖“services.AddRazorPages().AddRazorPagesOptions()”以允许集成测试获取或 post 页面没有伪造授权。

AddRazorPagesOptions essentially just configures the RazorPagesOptions在服务集合上,所以等价于:

services.Configure<RazorPagesOptions>(options =>
{
    options.Conventions.AuthorizeAreaFolder("xxxxxx", "/");
    // …
});

这也意味着要更改约定,您可以重新配置 RazorPagesOptions 并直接修改约定集合。不幸的是,IPageConvention types are private, so you cannot look for the entries that are added by AuthorizeAreaFolder directly and remove them with the RemoveType method. However, you could clear 整个集合完全删除了所有约定:

services.Configure<RazorPagesOptions>(options =>
{
    options.Conventions.Clear();
});