集成测试期间的 ASP.NET Core 3 模拟授权

ore*_*tis 14 c# asp.net integration-testing

我正在使用 ASP.NET 核心来构建 API,并且我正在尝试从 .NET 核心 2.2 升级到 .NET 核心 3.1。

我正在使用该[Authorize]属性来保护 API 端点,并且我想在集成测试期间绕过它。

我设法创建了一个自定义的 AuthenticationHandler 来验证一个假用户,以及一个授权任何人(包括匿名用户)的授权处理程序。

我的问题是注入到身份验证处理程序中的用户没有传播到授权处理程序并且过滤器DenyAnonymousAuthorizationRequirement失败,因为上下文中的用户为空。

有没有人处理过类似的事情?

顺便说一下,这个类DenyAnonymousAuthorizationRequirement是一个 Microsoft 类,我复制了它在 IDE 中出现的代码,只是为了在这里发帖。

我的自定义 AuthenticationHandler:

  public class TestAuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
  {
        public TestAuthHandler(IOptionsMonitor<AuthenticationSchemeOptions> options,
                               ILoggerFactory logger,
                               UrlEncoder encoder,
                               ISystemClock clock)
            : base(options, logger, encoder, clock) { }

        protected override Task<AuthenticateResult> HandleAuthenticateAsync()
        {
            ClaimsPrincipal fakeUser = FakeUserUtil.FakeUser();
            var ticket = new AuthenticationTicket(fakeUser, "Test");
            var result = AuthenticateResult.Success(ticket);
            return Task.FromResult(result);
        }
  }
Run Code Online (Sandbox Code Playgroud)

授权要求:

public class DenyAnonymousAuthorizationRequirement : AuthorizationHandler<DenyAnonymousAuthorizationRequirement>, IAuthorizationRequirement
    {

        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, DenyAnonymousAuthorizationRequirement requirement)
        {
            var user = context.User;
            var userIsAnonymous =
                user?.Identity == null ||
                !user.Identities.Any(i => i.IsAuthenticated);
            if (!userIsAnonymous)
            {
                context.Succeed(requirement);
            }
            return Task.CompletedTask;
        }
    }
Run Code Online (Sandbox Code Playgroud)

使用上述类的 ConfigureServices 方法中的代码:

 public void ConfigureServices(IServiceCollection services)
 {

            services.AddAuthentication("Test")
                    .AddScheme<AuthenticationSchemeOptions, TestAuthHandler>("Test", null);
            services.AddAuthorization(configure =>
            {
                var builder = new AuthorizationPolicyBuilder(new List<string> {"Test"}.ToArray())
                    .AddRequirements(new DenyAnonymousAuthorizationRequirement());
                configure.DefaultPolicy = builder.Build();
            });
            services.AddControllers()
                    .SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
                    .AddNewtonsoftJson(options =>
                                           options.SerializerSettings.ReferenceLoopHandling =
                                               ReferenceLoopHandling.Ignore);

}
Run Code Online (Sandbox Code Playgroud)

小智 15

Have a related problem and have stumbled on this article here

it shows that you can override the user that is set in the HttpContext this way:

class FakeUserFilter : IAsyncActionFilter
{
   public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
   {
    context.HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
    {
        new Claim(ClaimTypes.NameIdentifier, "123"),
        new Claim(ClaimTypes.Name, "Test user"),
        new Claim(ClaimTypes.Email, test@example.com),
        new Claim(ClaimTypes.Role, "Admin")
    }));

    await next();
  }   }
Run Code Online (Sandbox Code Playgroud)

and then inject it in ConfigureTestServices:

builder.ConfigureTestServices(services =>
        {
            services.AddMvc(options =>
            {                   
                options.Filters.Add(new AllowAnonymousFilter());
                options.Filters.Add(new FakeUserFilter());
            })
            .AddApplicationPart(typeof(Startup).Assembly);
        });
Run Code Online (Sandbox Code Playgroud)

Hope this helps

  • 博客文章很棒,比文档好得多。Gunnar 的另一篇文章帮助我获得不同的用户进行集成测试:https://gunnarpeipman.com/aspnet-core-integration-tests-users-roles/ (3认同)

Mat*_*ier 3

在“模拟身份验证”会话中查看此文档https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-3.1。我认为您需要在创建客户端后添加此代码:

client.DefaultRequestHeaders.Authorization = 
    new AuthenticationHeaderValue("Test");
Run Code Online (Sandbox Code Playgroud)