用户在策略中缺少身份认证方案的身份认证

问题描述 投票:1回答:1

我创建了一个ASP.NET Core 3.1应用程序,它使用2种认证类型--cookie和JWT bearer。

我设置了一个方案,根据请求的路径将用户重定向到合适的方案。

.AddAuthentication(sharedOptions =>
{
    sharedOptions.DefaultScheme = "smart";
    sharedOptions.DefaultChallengeScheme = "smart";
})
.AddPolicyScheme("smart", "Bearer Authorization or Cookie", options =>
{
    options.ForwardDefaultSelector = context =>
    {
        var requestPath = context.Request.Path;

        if (CookiePolicyPathRegex.IsMatch(requestPath))
        {
            return CookieAuthenticationDefaults.AuthenticationScheme;
        }

        return JwtBearerDefaults.AuthenticationScheme;
    };
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOAuthServiceScheme(Configuration); // Custom handler for JWT

我设置了这样的授权策略。

options.AddPolicy(ApiPolicies.CookiePolicy, policy =>
{
    // policy.AddAuthenticationSchemes(CookieAuthenticationDefaults.AuthenticationScheme);
    policy.RequireAuthenticatedUser();
    policy.RequireRole(Roles.Access);
});

options.AddPolicy(ApiPolicies.JwtPolicy, policy =>
{
    policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
    policy.RequireAuthenticatedUser();
});

这样做很好,正确的策略被触发了,但我有一个问题。在我的集成测试中,我使用了一个中间件,它为cookie认证添加了ClaimsIdentity。

public async Task Invoke(HttpContext context)
{
    //  Removed for brevity

    var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);

    context.User = new ClaimsPrincipal(claimsIdentity);

    await _next(context);
}

这个中间件被设置为在Auth中间件之前运行。

ConfigureAdditionalMiddleware(app);

app.UseAuthentication();
app.UseAuthorization();

如果我取消评论 // policy.AddAuthenticationSchemes(CookieAuthenticationDefaults.AuthenticationScheme); 的部分,授权部分没有看到在中间件中创建的个人信息。如果我不对它进行注释,那么个人信息就在那里,包括声明、认证类型和其他一切。如果我查看转发到两个认证方案的PolicyScheme,个人信息就在那里。

我的问题是,为什么添加 CookieAuthenticationDefaults.AuthenticationScheme 以某种方式隐藏用相同的认证类型创建的用户身份?

c# asp.net-core authentication asp.net-identity claims-based-identity
1个回答
2
投票

授权中间件将评估您的策略,并将运行认证逻辑,该逻辑将覆盖用户.Context。

这里是相关的代码片段(我删除并简化了代码,以突出相关部分)。

public virtual async Task<AuthenticateResult> AuthenticateAsync(AuthorizationPolicy policy, HttpContext context)
{
    if (policy.AuthenticationSchemes != null && policy.AuthenticationSchemes.Count > 0)
    {
        var newPrincipal = await context.AuthenticateAsync(scheme).Principal;

        if (newPrincipal != null)
        {
            context.User = newPrincipal;
            return AuthenticateResult.Success(new AuthenticationTicket(newPrincipal, string.Join(";", policy.AuthenticationSchemes)));
        }
        else
        {
            context.User = new ClaimsPrincipal(new ClaimsIdentity());
            return AuthenticateResult.NoResult();
        }
    }
    ...
}

所以,正如你所看到的,当你为你的策略定义一个方案时,然后你输入 "if "语句(这将会设置一个新的 "if "语句)。context.User如果你评论这一行,验证逻辑将不会运行,而你的自定义用户对象将在那里。

© www.soinside.com 2019 - 2024. All rights reserved.