如何在集成测试中从服务中删除 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();
});
我使用自定义 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();
});