Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 用户在具有身份验证方案的策略中缺少标识_C#_Asp.net Core_Authentication_Asp.net Identity_Claims Based Identity - Fatal编程技术网

C# 用户在具有身份验证方案的策略中缺少标识

C# 用户在具有身份验证方案的策略中缺少标识,c#,asp.net-core,authentication,asp.net-identity,claims-based-identity,C#,Asp.net Core,Authentication,Asp.net Identity,Claims Based Identity,我已经创建了一个ASP.NET Core 3.1应用程序,它使用两种身份验证类型—cookie和JWT承载 我已设置一个方案,根据请求的路径将用户重定向到正确的方案: .AddAuthentication(sharedOptions => { sharedOptions.DefaultScheme = "smart"; sharedOptions.DefaultChallengeScheme = "smart"; }) .AddPolicyScheme("smart", "

我已经创建了一个ASP.NET Core 3.1应用程序,它使用两种身份验证类型—cookie和JWT承载

我已设置一个方案,根据请求的路径将用户重定向到正确的方案:

.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)cookie策略的一部分,授权部分看不到在中间件中创建的标识。如果我将其保留为注释,则标识就在那里,包含声明、身份验证类型和所有内容。如果我查看转发到两个身份验证方案的PolicyScheme,标识就在那里


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

授权中间件将评估您的策略,并运行将覆盖用户的身份验证逻辑。上下文

  • 请参见此处的源代码
以下是相关的代码片段(我删除并简化了代码以突出显示相关部分):

公共虚拟异步任务AuthenticateAsync(授权策略,HttpContext上下文) { if(policy.AuthenticationSchemes!=null&&policy.AuthenticationSchemes.Count>0) { var newPrincipal=await context.authenticateSync(scheme.Principal); if(newPrincipal!=null) { context.User=newPrincipal; 返回AuthenticateResult.Success(新的AuthenticationTicket(newPrincipal,string.Join(“;”,policy.AuthenticationSchemes)); } 其他的 { context.User=newclaimsprincipal(newclaimsidentity()); 返回AuthenticateResult.NoResult(); } } ... }

因此,正如您所看到的,当您为策略定义方案时,输入“if”语句(这将设置一个新的
context.User
,如果您对该行进行注释,身份验证逻辑将不会运行,并且您的自定义用户对象将在那里

您是否可以将中间件放置在
UseAuthentication
中间件之后,以便身份尚未设置?好的一点是,我编辑了这篇文章以包含Startup.cs的这一部分,但是依我看应该没问题。身份在转发到身份验证方案的方案中是可见的。身份可以在
UseAuthentication
UseAuthentication
中设置,请参阅本文了解
UseAuthentication
的具体功能。非常感谢您的研究!我想这会是一件好事就像这样。所以让它在测试中工作的唯一方法是制作一个实际的cookie并在请求中发送它?我希望能够在策略中不断添加方案,以便将其与cookie选项绑定。制作cookie将非常困难,因为您必须了解cookie auth+cookie sym的内部结构度量加密/解密密钥。
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();
        }
    }
    ...
}