我正在尝试在 ASP.Net Core 2中构建一个自定义身份验证处理程序。跟进 ASP.NET 核心 2.0 身份验证中间件和为什么 Asp.Net 核心身份验证方案是必需的主题,我创建了特定的类。注册发生如下:
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(AuthenticationSchemes= Constants.NoOpSchema)]
[Route("api/[controller]")]
public class IndividualsController : Controller
但是我希望不必设置模式,因为它应该是动态添加的。我一删除Scheme属性,就像这样:
[Authorize]
[Route("api/[controller]")]
public class IndividualsController : Controller
它不再工作了。
我希望设置DefaultScheme财产可以完成这项工作。有趣的是,我没有发现任何关于这个话题的具体讨论。我是在这里做错了什么,还是我预期的结果错了?
编辑:感谢您的问题,它对我有很大帮助。似乎映射身份验证中间件正在使用的 DefaultScheme,我只在 CustomAuthHandler 到位时使用。因此,我必须始终添加身份验证中间件。
编辑2:可惜还是不行。为了加强我的问题:我像往常一样添加中间件:
app.UseAuthentication();
app.UseMvc();
现在我进入我的处理程序,它看起来像这样:
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)));
}
但即使我总是取得成功,我也会得到401分。我想我必须更深入地挖掘并设置一些声明,但不幸的是,微软的Handlers很难分析,因为它们包含很多代码。
ASP.NET 核心2答案
您必须设置与身份验证方案相关的默认授权策略:
services.AddAuthorization(options => {
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes(Constants.NoOpSchema)
.RequireAuthenticatedUser()
.Build();
});
ASP.NETCore 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);
}
}
并在ConfigureServices
方法中使用它,如下所示:
services
.AddAuthentication(NoOpAuthHandler.NoOpSchema)
.AddNoOpAuth();
确保您的管道中有身份验证中间件,并将其放在MVC之前。
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
///
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
});
///
}
更新
请尝试在HandleAuthenticateAsync
方法中使用此代码。
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);
}
我忍受了几个小时,在我的情况下,问题是默认的身份验证中间件类。
更具体地说;如果在请求管道中的自定义中间件中设置声明主体,如下所示;
< code > httpcontext . context . user = new ClaimsPrincipal(identity);这将覆盖您的默认身份验证配置设置,
我做了什么来解决;删除自定义中间件并添加应用。使用身份验证();
在 配置部分 启动.cs 和 授权 属性检查配置部分中设置的任何内容作为默认值;
这是我的;
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
};
});