C# ASP.Net core 2:忽略默认身份验证方案

C# ASP.Net core 2:忽略默认身份验证方案,c#,authentication,asp.net-core,asp.net-core-mvc,C#,Authentication,Asp.net Core,Asp.net Core Mvc,我正在尝试在ASP.NETCore2中构建一个自定义AuthenticationHandler。在像和这样的主题之后,我创建了特定的类。注册过程如下所示: services.AddAuthentication( options => { options.DefaultScheme = Constants.NoOpSchema; options.DefaultAuthenticateScheme = Constants.NoOpSchema;

我正在尝试在ASP.NETCore2中构建一个自定义AuthenticationHandler。在像和这样的主题之后,我创建了特定的类。注册过程如下所示:

services.AddAuthentication(
    options =>
    {
        options.DefaultScheme = Constants.NoOpSchema;
        options.DefaultAuthenticateScheme = Constants.NoOpSchema;
        options.DefaultChallengeScheme = Constants.NoOpSchema;
        options.DefaultSignInScheme = Constants.NoOpSchema;
        options.DefaultSignOutScheme = Constants.NoOpSchema; 
        options.DefaultForbidScheme = Constants.NoOpSchema;
    }
).AddScheme<CustomAuthOptions, CustomAuthHandler>(Constants.NoOpSchema, "Custom Auth", o => { });
[Authorize]
[Route("api/[controller]")]
public class IndividualsController : Controller
public class NoOpAuthHandler : AuthenticationHandler<NoOpAuthOptions>
{
    public const string NoOpSchema = "NoOp";

    public NoOpAuthHandler(IOptionsMonitor<NoOpAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
    {
    }

    protected override Task<AuthenticateResult> HandleAuthenticateAsync() => Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(Context.User, NoOpSchema)));
}
services
  .AddAuthentication(NoOpAuthHandler.NoOpSchema)
  .AddNoOpAuth();
但是我不想设置模式,因为它应该被动态添加。一旦我移除Scheme属性,如下所示:

services.AddAuthentication(
    options =>
    {
        options.DefaultScheme = Constants.NoOpSchema;
        options.DefaultAuthenticateScheme = Constants.NoOpSchema;
        options.DefaultChallengeScheme = Constants.NoOpSchema;
        options.DefaultSignInScheme = Constants.NoOpSchema;
        options.DefaultSignOutScheme = Constants.NoOpSchema; 
        options.DefaultForbidScheme = Constants.NoOpSchema;
    }
).AddScheme<CustomAuthOptions, CustomAuthHandler>(Constants.NoOpSchema, "Custom Auth", o => { });
[Authorize]
[Route("api/[controller]")]
public class IndividualsController : Controller
public class NoOpAuthHandler : AuthenticationHandler<NoOpAuthOptions>
{
    public const string NoOpSchema = "NoOp";

    public NoOpAuthHandler(IOptionsMonitor<NoOpAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
    {
    }

    protected override Task<AuthenticateResult> HandleAuthenticateAsync() => Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(Context.User, NoOpSchema)));
}
services
  .AddAuthentication(NoOpAuthHandler.NoOpSchema)
  .AddNoOpAuth();
它不再工作了

我希望,设置DefaultScheme属性可以完成这项工作。有趣的是,我没有发现关于这个话题的任何具体讨论。 我是做错了什么,还是我的预期结果错了

编辑:谢谢你的提问,这对我帮助很大。似乎身份验证中间件正在使用映射DefaultScheme,而我只在CustomAuthHandler不存在时使用它。因此,我必须始终添加AuthenticationMiddleware

Edit2:不幸的是,它仍然不起作用。为了加强我的问题:我像往常一样添加中间件:

app.UseAuthentication();
app.UseMvc();
现在我进入我的处理器,它看起来像这样:

services.AddAuthentication(
    options =>
    {
        options.DefaultScheme = Constants.NoOpSchema;
        options.DefaultAuthenticateScheme = Constants.NoOpSchema;
        options.DefaultChallengeScheme = Constants.NoOpSchema;
        options.DefaultSignInScheme = Constants.NoOpSchema;
        options.DefaultSignOutScheme = Constants.NoOpSchema; 
        options.DefaultForbidScheme = Constants.NoOpSchema;
    }
).AddScheme<CustomAuthOptions, CustomAuthHandler>(Constants.NoOpSchema, "Custom Auth", o => { });
[Authorize]
[Route("api/[controller]")]
public class IndividualsController : Controller
public class NoOpAuthHandler : AuthenticationHandler<NoOpAuthOptions>
{
    public const string NoOpSchema = "NoOp";

    public NoOpAuthHandler(IOptionsMonitor<NoOpAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
    {
    }

    protected override Task<AuthenticateResult> HandleAuthenticateAsync() => Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(Context.User, NoOpSchema)));
}
services
  .AddAuthentication(NoOpAuthHandler.NoOpSchema)
  .AddNoOpAuth();
public类NoOpAuthHandler:AuthenticationHandler
{
public const string NoOpSchema=“NoOp”;
public NoOpAuthHandler(IOptionsMonitor选项、iLogger工厂记录器、UrlEncoder编码器、ISystemClock时钟):基本(选项、记录器、编码器、时钟)
{
}
受保护的覆盖任务handleAuthenticationAsync()=>Task.FromResult(AuthenticateResult.Success)(新的AuthenticationTicket(Context.User,NoOpSchema));
}

但即使我总是成功,我也会得到401。我认为我必须更深入地挖掘,并设定一些声明,但不幸的是,来自Microsoft的处理程序很难分析,因为它们包含大量代码。

确保您的管道中有身份验证中间件,并将其放在MVC之前

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    ///

    app.UseAuthentication();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller}/{action=Index}/{id?}");
    });
    ///
}
更新

尝试在
handleAuthenticationAsync
方法中使用此代码

protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
    List<Claim> claims = new List<Claim>();
    ClaimsIdentity claimsIdentity = new ClaimsIdentity(claims, Scheme.Name);
    ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
    AuthenticationTicket authenticationTicket = new AuthenticationTicket(claimsPrincipal, Scheme.Name);
    return AuthenticateResult.Success(authenticationTicket);
}
protectedoverride异步任务handleAuthenticationAsync()
{
列表声明=新列表();
ClaimsIdentity ClaimsIdentity=新的ClaimsIdentity(索赔,Scheme.Name);
ClaimsPrincipal ClaimsPrincipal=新的ClaimsPrincipal(索赔实体);
AuthenticationTicket AuthenticationTicket=新的AuthenticationTicket(claimsPrincipal,Scheme.Name);
返回AuthenticateResult.Success(authenticationTicket);
}

ASP.Net核心2答案

您必须设置与身份验证方案关联的默认授权策略:

services.AddAuthorization(options => {
  options.DefaultPolicy = new AuthorizationPolicyBuilder()
    .AddAuthenticationSchemes(Constants.NoOpSchema)
    .RequireAuthenticatedUser()
    .Build();
});
ASP.Net核心3答案

在ASP.Net Core 3中,事情显然发生了一些变化,因此您需要创建一个扩展方法来添加身份验证处理程序:

public static class NoOpAuthExtensions
{
    public static AuthenticationBuilder AddNoOpAuth(this AuthenticationBuilder builder)
        => builder.AddNoOpAuth(NoOpAuthHandler.NoOpSchema, _ => { });
    public static AuthenticationBuilder AddNoOpAuth(this AuthenticationBuilder builder, Action<NoOpAuthOptions> configureOptions)
        => builder.AddNoOpAuth(NoOpAuthHandler.NoOpSchema, configureOptions);
    public static AuthenticationBuilder AddNoOpAuth(this AuthenticationBuilder builder, string authenticationScheme, Action<NoOpAuthOptions> configureOptions)
        => builder.AddNoOpAuth(authenticationScheme, null, configureOptions);
    public static AuthenticationBuilder AddNoOpAuth(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<NoOpAuthOptions> configureOptions)
    {
        return builder.AddScheme<NoOpAuthOptions, NoOpAuthHandler>(authenticationScheme, displayName, configureOptions);
    }
}
试试这个

services.AddAuthentication(
        options =>
        {
            options.DefaultAuthenticateScheme = "Cookie"
            options.DefaultChallengeScheme = Constants.NoOpSchema;
            options.DefaultSignInScheme = "Cookie";
        }
    )
    .AddCookie("Cookie")
    .AddScheme<CustomAuthOptions, CustomAuthHandler>(Constants.NoOpSchema, "Custom Auth", o => { });
services.AddAuthentication(
选项=>
{
options.DefaultAuthenticateScheme=“Cookie”
options.DefaultChallengeScheme=Constants.NoOpSchema;
options.defaultSignenscheme=“Cookie”;
}
)
.AddCookie(“Cookie”)
.AddScheme(Constants.NoOpSchema,“自定义身份验证”,o=>{});

我经历了几个小时,在我的例子中,问题是默认的AuthenticationMiddleware类。 更具体地说; 如果您在请求管道中的自定义中间件中设置ClaimsPrincipal,如下所示

HttpContext.context.User=newclaimsprincipal(标识)
这将覆盖默认的身份验证配置设置

我做了什么来解决问题;删除自定义中间件并添加
app.UseAuthentication(),Authroize属性检查Configure部分中设置为默认值的内容

这是我的

services.AddAuthentication(x =>
            {
                x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, x =>
            {
                x.RequireHttpsMetadata = false;
                x.SaveToken = true;
                x.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateLifetime = true,
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    ClockSkew = TimeSpan.Zero
                };
            });

在.NET Core 3.1中,我必须手动向端点添加
[Authorize(authorization(authorizationschemes=“Bearer”)]
,而不是简单的
[Authorize]
,以使身份验证如我所期望的那样发挥作用。以下配置更改解决了该问题:

services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = "Bearer";
    })

您是否在中间件管道中添加了
app.UseAuthentication()
?删除
AuthenticationSchemes
时会出现什么错误?CustomAuthHandler做什么?我相信您知道,但您可以继承authorize属性以避免AuthenticationSchemes=Constants.NoOpSchemaThis对我有效。我不确定
DefaultAuthenticateScheme
的实际用途,但它不是用于设置默认的[Authorize]方案。另一个注意事项是,在.NET Core 3/5中,请确保在
app.UseAuthorization()
之前有
app.UseAuthorization
。我每天有两个小时:)