How to override program.cs to disable authentication and authorization for ASP.NET Core Razor Pages web app?

huangapple go评论73阅读模式
英文:

How to override program.cs to disable authentication and authorization for ASP.NET Core Razor Pages web app?

问题

I have this test class that fails with an error.

> System.Net.Http.HttpRequestException : Response status code does not
> indicate success: 302 (Found).

If I manually commented out the code for authentication and authorization in program.cs, the test class works as expected.

In program.cs (I am using .NET 6):

//builder.Services.AddRazorPages()
//        .AddRazorPagesOptions(options => {
//            options.Conventions.AuthorizeFolder("/"); // apply the [Authorize] attribute to all pages for all folders
//        })
//        .AddMicrosoftIdentityUI();
builder.Services.AddRazorPages();

How to override program.cs in my test class to disable authentication and authorization for ASP.NET Core Razor Pages web app?

This is my test class:

public class IntegrationTests : IClassFixture<WebApplicationFactory<Program>> {
    private readonly WebApplicationFactory<Program> _factory;

    public IntegrationTests(WebApplicationFactory<Program> factory) {
        _factory = factory.WithWebHostBuilder(builder =>
        {
            // Override the services configuration for testing
            builder.ConfigureServices(services =>
            {
                // Remove the authorization policy for Razor Pages                    
                services.AddRazorPages();

            });
        });
    }

    [Theory]
    [InlineData("/")]
    public async Task Get_EndpointsReturnSecurePageAsync(string url) {
        // Arrange
        var client = _factory.CreateClient();

        // Act
        var response = await client.GetAsync(url);

        // Assert
        response.EnsureSuccessStatusCode(); // Status Code 200-299
        Assert.Equal("text/html; charset=utf-8",
            response.Content.Headers.ContentType.ToString());
    }
}
英文:

I have this test class that fails with an error.

> System.Net.Http.HttpRequestException : Response status code does not
> indicate success: 302 (Found).

If I manually commented out the code for authentication and authorization in program.cs, the test class works as expected.

In program.cs (I am using .NET 6):

//builder.Services.AddRazorPages()
//        .AddRazorPagesOptions(options => {
//            options.Conventions.AuthorizeFolder("/"); // apply the [Authorize] attribute to all pages for all folders
//        })
//        .AddMicrosoftIdentityUI();
builder.Services.AddRazorPages();

How to override program.cs in my test class to disable authentication and authorization for ASP.NET Core Razor Pages web app?

This is my test class:

public class IntegrationTests : IClassFixture<WebApplicationFactory<Program>> {
    private readonly WebApplicationFactory<Program> _factory;

    public IntegrationTests(WebApplicationFactory<Program> factory) {
        _factory = factory.WithWebHostBuilder(builder =>
        {
            // Override the services configuration for testing
            builder.ConfigureServices(services =>
            {
                // Remove the authorization policy for Razor Pages                    
                services.AddRazorPages();

            });
        });
    }

    [Theory]
    [InlineData("/")]
    public async Task Get_EndpointsReturnSecurePageAsync(string url) {
        // Arrange
        var client = _factory.CreateClient();

        // Act
        var response = await client.GetAsync(url);

        // Assert
        response.EnsureSuccessStatusCode(); // Status Code 200-299
        Assert.Equal("text/html; charset=utf-8",
            response.Content.Headers.ContentType.ToString());
    }
}

答案1

得分: 5

ASP.NET Core集成测试中的文档-模拟身份验证中的文档:

测试应用程序可以在ConfigureTestServices中模拟AuthenticationHandler<TOptions>以测试身份验证和授权的方面。

在上述链接中提供了代码示例:

public class TestAuthHandler : AuthenticationHandler&lt;AuthenticationSchemeOptions&gt;
{
    public TestAuthHandler(IOptionsMonitor&lt;AuthenticationSchemeOptions&gt; options,
        ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
        : base(options, logger, encoder, clock)
    {
    }

    protected override Task&lt;AuthenticateResult&gt; HandleAuthenticateAsync()
    {
        var claims = new[] { new Claim(ClaimTypes.Name, &quot;Test user&quot;) };
        var identity = new ClaimsIdentity(claims, &quot;Test&quot;);
        var principal = new ClaimsPrincipal(identity);
        var ticket = new AuthenticationTicket(principal, &quot;TestScheme&quot;);

        var result = AuthenticateResult.Success(ticket);

        return Task.FromResult(result);
    }
}

将身份验证处理程序添加到测试中使用的服务集合:

[Fact]
public async Task Get_SecurePageIsReturnedForAnAuthenticatedUser()
{
    // Arrange
    var client = _factory.WithWebHostBuilder(builder =&gt;
        {
            builder.ConfigureTestServices(services =&gt;
            {
                services.AddAuthentication(defaultScheme: &quot;TestScheme&quot;)
                    .AddScheme&lt;AuthenticationSchemeOptions, TestAuthHandler&gt;(
                        &quot;TestScheme&quot;, options =&gt; { });
            });
        })
        .CreateClient(new WebApplicationFactoryClientOptions
        {
            AllowAutoRedirect = false,
        });

    client.DefaultRequestHeaders.Authorization =
        new AuthenticationHeaderValue(scheme: &quot;TestScheme&quot;);

    //Act
    var response = await client.GetAsync(&quot;/SecurePage&quot;);

    // Assert
    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}
英文:

From the documentation at Integration tests in ASP.NET Core - Mock authentication
> The test app can mock an AuthenticationHandler<TOptions> in ConfigureTestServices in order to test aspects of authentication and authorization.

Code examples given in the above link:

public class TestAuthHandler : AuthenticationHandler&lt;AuthenticationSchemeOptions&gt;
{
    public TestAuthHandler(IOptionsMonitor&lt;AuthenticationSchemeOptions&gt; options,
        ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
        : base(options, logger, encoder, clock)
    {
    }

    protected override Task&lt;AuthenticateResult&gt; HandleAuthenticateAsync()
    {
        var claims = new[] { new Claim(ClaimTypes.Name, &quot;Test user&quot;) };
        var identity = new ClaimsIdentity(claims, &quot;Test&quot;);
        var principal = new ClaimsPrincipal(identity);
        var ticket = new AuthenticationTicket(principal, &quot;TestScheme&quot;);

        var result = AuthenticateResult.Success(ticket);

        return Task.FromResult(result);
    }
}

Add the authentication handler to the services collection used in the test:

[Fact]
public async Task Get_SecurePageIsReturnedForAnAuthenticatedUser()
{
    // Arrange
    var client = _factory.WithWebHostBuilder(builder =&gt;
        {
            builder.ConfigureTestServices(services =&gt;
            {
                services.AddAuthentication(defaultScheme: &quot;TestScheme&quot;)
                    .AddScheme&lt;AuthenticationSchemeOptions, TestAuthHandler&gt;(
                        &quot;TestScheme&quot;, options =&gt; { });
            });
        })
        .CreateClient(new WebApplicationFactoryClientOptions
        {
            AllowAutoRedirect = false,
        });

    client.DefaultRequestHeaders.Authorization =
        new AuthenticationHeaderValue(scheme: &quot;TestScheme&quot;);

    //Act
    var response = await client.GetAsync(&quot;/SecurePage&quot;);

    // Assert
    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}

答案2

得分: 1

你可以尝试在调用AddRazorPages之前移除配置的RazorPagesOptions选项:

public IntegrationTests(WebApplicationFactory&lt;Program&gt; factory) {
    _factory = factory.WithWebHostBuilder(builder =&gt;
    {
        // Override the services configuration for testing
        builder.ConfigureServices(services =&gt;
        {
            // Remove the authorization policy for Razor Pages  
            services.RemoveAll&lt;IConfigureOptions&lt;RazorPagesOptions&gt;&gt;();     
            services.AddRazorPages().AddRazorPagesOptions(_ =&gt; {}); 
        });
    });
}

或者:

public IntegrationTests(WebApplicationFactory&lt;Program&gt; factory) {
    _factory = factory.WithWebHostBuilder(builder =&gt;
    {
        // Override the services configuration for testing
        builder.ConfigureServices(services =&gt;
        {
            // Remove the authorization policy for Razor Pages  
            services.RemoveAll&lt;IConfigureOptions&lt;RazorPagesOptions&gt;&gt;();     
            services.AddRazorPages();
        });
    });
}
英文:

You can try removing the configured RazorPagesOptions options before calling the AddRazorPages:

public IntegrationTests(WebApplicationFactory&lt;Program&gt; factory) {
    _factory = factory.WithWebHostBuilder(builder =&gt;
    {
        // Override the services configuration for testing
        builder.ConfigureServices(services =&gt;
        {
            // Remove the authorization policy for Razor Pages  
            services.RemoveAll&lt;IConfigureOptions&lt;RazorPagesOptions&gt;&gt;();     
            services.AddRazorPages().AddRazorPagesOptions(_ =&gt; {});
        });
    });
}

Or just:

public IntegrationTests(WebApplicationFactory&lt;Program&gt; factory) {
    _factory = factory.WithWebHostBuilder(builder =&gt;
    {
        // Override the services configuration for testing
        builder.ConfigureServices(services =&gt;
        {
            // Remove the authorization policy for Razor Pages  
            services.RemoveAll&lt;IConfigureOptions&lt;RazorPagesOptions&gt;&gt;();     
            services.AddRazorPages();
        });
    });
}

答案3

得分: 0

使用环境变量来完成。从安全角度看,这有多安全是另一个问题。

检查在 program.cs 中是否设置了该变量:

if (Environment.GetEnvironmentVariable("TEST_NO_AUTH") == "enabled")
{
	builder.Services.AddRazorPages();
}
else
{
	builder.Services.AddRazorPages()
		.AddRazorPagesOptions(options =>
		{
			options.Conventions.AuthorizeFolder("/"); // apply the [Authorize] attribute to all pages for all folders
		})
		.AddMicrosoftIdentityUI();
}

然后在测试构造函数中设置该变量:

Environment.SetEnvironmentVariable("TEST_NO_AUTH", "enabled");
英文:

Using an environment variable will do it. How safe this is from a security perspective is another question.

Check if the variable is set in program.cs:

if (Environment.GetEnvironmentVariable(&quot;TEST_NO_AUTH&quot;) == &quot;enabled&quot;)
{
	builder.Services.AddRazorPages();
}
else
{
	builder.Services.AddRazorPages()
		.AddRazorPagesOptions(options =&gt;
		{
			options.Conventions.AuthorizeFolder(&quot;/&quot;); // apply the [Authorize] attribute to all pages for all folders
		})
		.AddMicrosoftIdentityUI();
}

Then set the variable in the tests constructor.

Environment.SetEnvironmentVariable(&quot;TEST_NO_AUTH&quot;, &quot;enabled&quot;);

huangapple
  • 本文由 发表于 2023年5月7日 04:47:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76191062.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定