4

我目前有一个ASP 5/ASP Core Web API,我需要使用OWIN Test Server进行集成测试。我如何使用[授权]属性集成测试ASP 5/Core Web API

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

这是API的Startup.cs:

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错误代码。

这是我如何设置的OWIN测试服务器:

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结果。

我怎样才能成功伪造身份验证的用户,并绕过[授权],同时也为HttpRequest设置当前用户?

UPDATE: 如果注册我自己CookieAuthentication处理这样的:

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

我得到的302 Redirect到登录页面。该登入但是在正常工作时,我用这里面的TestMiddleware await context.Authentication.SignInAsync(TestingCookieAuthentication, claimsPrincipal)

回答

5

好了,所以我才弄明白为什么它不工作:)

在创建ClaimsPrincipal如果AuthenticationProvider必须包含在主要的构造。如果未提供认证类型,SignInAsync()功能将失败并且未对用户进行认证。

而不是做这个的:

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

必须指定像这样的AuthenticationHandler:

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