本文介绍了如何使用[Authorize]属性集成测试ASP 5/Core Web API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前拥有一个ASP 5/ASP Core Web API,我需要将其与OWIN测试服务器进行集成测试.

I currently have an ASP 5/ASP Core Web API that I need to integration test with the OWIN Test Server.

问题是我将IdentityServer用作生产中的授权服务器,并且不想将授权作为集成测试的一部分.

The problem is that I use IdentityServer as the authorization server in production and I do not want to include the authorization as part of my integration testing.

这是API的Startup.cs:

This is the Startup.cs of the API:

public Startup(IHostingEnvironment env)
{
    // Set up configuration sources.
    IConfigurationBuilder builder = new ConfigurationBuilder()
        .AddJsonFile("appsettings.json")
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true);

    if (env.IsEnvironment("Development"))
    {
        // This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
        builder.AddApplicationInsightsSettings(developerMode: true);
    }

    builder.AddEnvironmentVariables();
    Configuration = builder.Build().ReloadOnChanged("appsettings.json");
}

public IConfigurationRoot Configuration { get; set; }

// This method gets called by the runtime. Use this method to add services to the container
public IServiceProvider ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddApplicationInsightsTelemetry(Configuration);

    ConfigureEntityFrameworkDatabase(services, Configuration);

    services.AddIdentity<IdentityUser, IdentityRole>()
        .AddEntityFrameworkStores<HoehenSuchtIdentityDbContext>()
        .AddDefaultTokenProviders();

    ConfigureMvc(services);

    // register autofac as dependency resolver
    ContainerBuilder containerBuilder = new ContainerBuilder();

    // register all required autofac modules
    RegisterAutofacModules(containerBuilder);

    // register all automapper mappings as di services so there dependencies can be resolved
    ConfigureAutomapper(containerBuilder);

    ConfigureSwagger(services);

    // copy all asp core dependency injection registrations to autofac
    containerBuilder.Populate(services);
    IContainer container = containerBuilder.Build();

    return container.Resolve<IServiceProvider>();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

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

    // make sure the database was created and all migrations applied
    MigrateDatabase(app);
    app.ApplicationServices.GetService<HoehenSuchtDbContext>().EnsureSeedData(env);

    app.UseIISPlatformHandler();

    app.UseApplicationInsightsRequestTelemetry();
    app.UseApplicationInsightsExceptionTelemetry();

    ConfigureIdentityServer(app, Configuration);

    app.UseStaticFiles();

    app.UseMvc();

    //app.UseSwaggerGen(/*routeTemplate: "docs/{apiVersion}/swagger.json"*/);
    //app.UseSwaggerUi(/*baseRoute: "docs", swaggerUrl: "docs/v1/swagger.json"*/);
}

public static Action<IServiceCollection, IConfigurationRoot> ConfigureEntityFrameworkDatabase = (services, config) =>
{
    services.AddEntityFramework()
        .AddSqlServer()
        .AddDbContext<HoehenSuchtDbContext>(builder =>
            builder.UseSqlServer(config["Data:DefaultConnection:ConnectionString"]))
        .AddDbContext<HoehenSuchtIdentityDbContext>(builder =>
            builder.UseSqlServer(config["Data:IdentityConnection:ConnectionString"]));
};

public static Action<IServiceCollection> ConfigureMvc = services =>
{
    services.AddMvc().AddControllersAsServices(new List<Assembly> { typeof(Startup).GetTypeInfo().Assembly });
};

我已经尝试注册一种特殊的测试中间件,该中间件在理论上应进行身份验证并设置索赔主体.但是在OWIN管道的某处,身份验证被拒绝,并且我收到401错误代码.

I already tried registering a special test middleware that in theory should authenticate and set a claims principal. But somewhere down the OWIN pipeline the authentication is denied and I get a 401 error code.

这是我设置OWIN测试服务器的方式:

This is how I setup the OWIN Test Server:

Startup.MigrateDatabase = app =>
{
    app.ApplicationServices.GetService<HoehenSuchtDbContext>().Database.EnsureCreated();
};
Startup.ConfigureEntityFrameworkDatabase = ApiTestServer.ConfigureInMemoryDatabase;
Startup.ConfigureIdentityServer = (app, config) =>
{
    app.ApplicationServices.GetService<HoehenSuchtDbContext>().EnsureSeedData(new HostingEnvironment {EnvironmentName = "development" });

    app.UseMiddleware<AuthenticatedTestRequestMiddleware>();
};
Server = new TestServer(TestServer.CreateBuilder().UseStartup<Startup>());

这是我的自定义AuthenticatedTestRequestMiddleware:

public class AuthenticatedTestRequestMiddleware
{
    public const string TestingCookieAuthentication = "TestCookieAuthentication";
    public const string TestingHeader = "X-Integration-Testing";
    public const string TestingHeaderValue = "78EAAA45-E68B-43C7-9D12-3A5F1E646BD5";

    private readonly RequestDelegate _next;

    public AuthenticatedTestRequestMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        if (context.Request.Headers.Keys.Contains(TestingHeader) && context.Request.Headers[TestingHeader].First().Equals(TestingHeaderValue))
        {
            // fake authenticated the user
            ClaimsIdentity claimsIdentity = new ClaimsIdentity();
            claimsIdentity.AddClaims(new List<Claim>
            {
                new Claim(ClaimTypes.Name, "admin"),
                new Claim(ClaimTypes.NameIdentifier, UserSeedData.AdminUserId)
            });
            ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
            context.User = claimsPrincipal;
        }

        await _next(context);
    }
}

已设置主体并以给定的ID存在于数据库中,但是调用next(context)后,我会得到401 Unauthorized结果.

The principal is set and exists in the database with the given ID, but after I call next(context) I get an 401 Unauthorized result.

如何在为HttpRequest设置当前用户的同时成功伪造对用户的身份验证并绕过[Authorize]?

How can I successfully fake authenticate the user and bypass the [Authorize] while also setting the current User for the HttpRequest?

更新:如果我这样注册自己的CookieAuthentication处理程序:

UPDATE:If I register my own CookieAuthentication handler like that:

app.UseCookieAuthentication(options =>
{
    options.AuthenticationScheme = AuthenticatedTestRequestMiddleware.TestingCookieAuthentication;
    options.AutomaticAuthenticate = true;
    options.AutomaticChallenge = true;
});

我将302 Redirect转到登录页面.但是,当我在TestMiddleware await context.Authentication.SignInAsync(TestingCookieAuthentication, claimsPrincipal)

I get the 302 Redirect to the login page. The signin however is working correctly when I use this inside the TestMiddleware await context.Authentication.SignInAsync(TestingCookieAuthentication, claimsPrincipal)

推荐答案

好,所以我发现了为什么它不起作用:)

Ok so I found out why it does not work :)

在创建ClaimsPrincipal时,必须在主体的构造函数中包括AuthenticationProvider.如果未提供身份验证类型,则SignInAsync()函数将失败并且不会对用户进行身份验证.

When creating the ClaimsPrincipal the AuthenticationProvider must be included in the constructor of the principal. If the authentication type is not provided the SignInAsync() function will fail and not authenticated the user.

而不是这样做:

ClaimsIdentity claimsIdentity = new ClaimsIdentity(new List<Claim>
{
    new Claim(ClaimTypes.Name, "admin"),
    new Claim(ClaimTypes.NameIdentifier, UserSeedData.AdminUserId)
});

您必须像这样指定AuthenticationHandler:

You must specify the AuthenticationHandler like this:

ClaimsIdentity claimsIdentity = new ClaimsIdentity(new List<Claim>
{
    new Claim(ClaimTypes.Name, "admin"),
    new Claim(ClaimTypes.NameIdentifier, UserSeedData.AdminUserId)
}, TestingCookieAuthentication);

这篇关于如何使用[Authorize]属性集成测试ASP 5/Core Web API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-12 18:56