微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在集成测试中为 HttpContext.User.IsInRole 方法检查声明角色?

如何解决如何在集成测试中为 HttpContext.User.IsInRole 方法检查声明角色?

我有以下集成测试代码

TestAuthenticationHandler

此处理程序正在设置名为 John Doe 的测试用户

public class TestAuthenticationSchemeOptions : AuthenticationSchemeOptions
{
    public string Role { get; set; }
}

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

    protected override Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        var claims = new[]
        {
            new Claim(ClaimTypes.Name,"Test"),new Claim(ClaimTypes.NameIdentifier,Guid.NewGuid().ToString()),new Claim("MemberId",Options.Role),new Claim("MemberForename","John"),new Claim("MemberSurname","Doe")
        };

        var identity = new ClaimsIdentity(claims,"Test");
        var principal = new ClaimsPrincipal(identity);
        var ticket = new AuthenticationTicket(principal,"Test");

        var result = AuthenticateResult.Success(ticket);

        return Task.Fromresult(result);
    }
}

测试方法

方法使用上面的处理程序来注册用户并分配管理员角色

[Theory]
[InlineData("/home/index")]
public async Task GetServerSideRenderedPage_ReturnsOk(string url)
{
    // Arrange
    HttpClient client = _factory.WithWebHostBuilder(builder =>
    {
        builder.ConfigureTestServices(services =>
        {
            services.AddAuthentication("Test")
                    .AddScheme<TestAuthenticationSchemeOptions,TestAuthenticationHandler>("Test",options => options.Role = "Admin");
        });
    }).CreateClient();

    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Test");

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

    // Assert
    Assert.Equal(HttpStatusCode.OK,response.StatusCode);
    Assert.NotNull(response.Content);
    Assert.Equal("text/html",response.Content.Headers.ContentType.MediaType);
    Assert.True(response.Content.Headers.ContentLength > 0);
}

Startup.cs

启用身份验证(生产中不需要)

app.UseAuthentication();   

我需要测试的控制器动作

在生产中 HttpContext 不是 NULL,但在测试中它是 NULL。所以我不得不添加通过 IHttpContextAccessor 填充的 AuthenticationHandlerHttpContext 仍然是 NULL,但 IHttpContextAccessor.HttpContext 是可以的)

public class HomeController : Controller
{
    private readonly IHttpContextAccessor _httpContext;

    public HomeController(IHttpContextAccessor httpContext)
    {
        _httpContext = httpContext;
    }

    [HttpGet]
    public IActionResult Index()
    {
        var allowed = _httpContext.HttpContext.User.IsInRole("Admin");

        return View();
    }
}

我面临的问题是 allowed 属性false,但我向用户声明了 Admin 角色。

enter image description here

在生产中它有效,因为应用程序在 IIS 服务器上运行并且管理员角色(在生产中命名不同)是域安全组。所以 HttpContext 正在检查连接的用户是否是域组的成员,但我不知道如何在测试中伪造/模拟 IsInRole() 方法。我是否必须在 TestAuthenticationHandler添加一些额外的声明?

此处描述的设置在使用 [Authorize(Roles = "Admin")] 属性时有效,但我也需要使用 IsInRole() 方法

你有什么想法吗?

解决方

这里缺少的部分是特定的角色声明

var claims = new[]
{
    new Claim(ClaimTypes.Name,new Claim(ClaimTypes.Role,// <-- this line was missing
    new Claim("MemberId","Doe")
};

enter image description here

enter image description here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。