You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core集成测试:UseStatusCodePagesWithReExecute授权测试问题

解决ASP.NET Core集成测试中未授权场景无法触发自定义错误页面的问题

首先明确核心问题:你当前的TestAuthHandler返回AuthenticateResult.Fail属于认证失败(返回401),ASP.NET Core的认证中间件会直接终止管道返回401响应,导致UseStatusCodePagesWithReExecute中间件没有机会处理该状态码。而如果是已认证但未授权(返回403)的场景,授权中间件返回的状态码会被状态码页面中间件正常捕获。

针对两种场景分别给出解决方案:

场景1:测试已认证但未授权(403)

这更符合“用户未授权”的语义,调整TestAuthHandler返回合法的认证结果,但Claims不满足目标Policy的要求:

protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
    // 构造仅包含基础身份信息的Claims,不满足目标Policy的要求
    var claims = new List<Claim>
    {
        new Claim(ClaimTypes.NameIdentifier, "test-user-id"),
        new Claim(ClaimTypes.Name, "Test User")
    };
    var identity = new ClaimsIdentity(claims, "TestAuth");
    var principal = new ClaimsPrincipal(identity);
    var ticket = new AuthenticationTicket(principal, "TestAuth");

    return Task.FromResult(AuthenticateResult.Success(ticket));
}

此时访问受Policy保护的接口时,授权中间件会返回403状态码,UseStatusCodePagesWithReExecute会自动触发Home/403对应的HttpStatusCodeHandler方法。

场景2:测试未认证(401)

若确实需要测试未认证场景,需修改认证方案的OnChallenge事件,让它仅设置状态码而非直接终止管道,确保状态码页面中间件能捕获处理:

  1. 在Startup的认证配置中添加事件处理:
services.AddAuthentication("TestAuth")
    .AddScheme<AuthenticationSchemeOptions, TestAuthHandler>("TestAuth", options =>
    {
        options.Events = new AuthenticationEvents
        {
            OnChallenge = context =>
            {
                // 设置401状态码,阻止默认的Challenge响应逻辑
                context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                context.HandleResponse();
                return Task.CompletedTask;
            }
        };
    });
  1. 确保中间件顺序正确(状态码页面中间件需在认证/授权中间件之前注册):
app.UseExceptionHandler("/Home/Error");
// 先注册状态码页面中间件
app.UseStatusCodePagesWithReExecute("/Home/{0}");

// 再注册认证、授权中间件
app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "home_error",
        pattern: "Home/{statusCode}",
        defaults: new { controller = "Home", action = "HttpStatusCodeHandler" },
        constraints: new { statusCode = new IntRouteConstraint() });
    // 其他路由...
});

集成测试示例

编写测试用例验证错误页面是否被正确返回:

[Fact]
public async Task Unauthenticated_AccessSecurePage_Returns401ErrorPage()
{
    var client = _factory.CreateClient();
    var response = await client.GetAsync("/Secure/ProtectedAction");

    // 注意:StatusCodePagesWithReExecute会返回200状态码,内容为错误页面
    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
    var content = await response.Content.ReadAsStringAsync();
    // 验证页面内容包含预期的错误提示或状态码标识
    Assert.Contains("401 Unauthorized", content);
}

内容的提问来源于stack exchange,提问作者Dan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 02:25:34