在WebAPI .net核心项目中,我创建了一个中间件类来验证api密钥。通过对其进行验证,它会检索密钥在invoke方法内(用户或admin)具有的权限。
我通过一个开关来设置它的原理
GenericIdentity identity = new GenericIdentity("API");
GenericPrincipal principle = null;
//we have a valid api key, so set the role permissions of the key
switch (keyValidatorRes.Role)
{
case Roles.User:
principle = new GenericPrincipal(identity, new[] { "User" });
context.User = principle;
break;
case Roles.Admin:
principle = new GenericPrincipal(identity, new[] { "Admin" });
context.User = principle;
break;
default:
principle = new GenericPrincipal(identity, new[] { "Other" });
context.User = principle;
break;
}
在控制器方法上我有
[Authorize(Roles = "Admin")]
验证经过身份验证的api密钥的作用
如果用户具有管理原则,则按预期进行。但是,如果它具有用户或其他原理,那么我会收到关于
的错误没有DefaultForbidScheme
我到处搜索并通过客户计划将身份验证添加到我的startup.cs中
services.AddAuthentication(options=> {
options.DefaultForbidScheme = "forbidScheme";
options.AddScheme<AuthSchemeHandle>("forbidScheme", "Handle Forbidden");
});
并创建了 AuthSchemeHandle
public class AuthSchemeHandle : IAuthenticationHandler
{
private HttpContext _context;
public Task<AuthenticateResult> AuthenticateAsync()
{
return Task.FromResult(AuthenticateResult.NoResult());
}
public Task ChallengeAsync(AuthenticationProperties properties)
{
throw new NotImplementedException();
}
public Task ForbidAsync(AuthenticationProperties properties)
{
return Task.FromResult(AuthenticateResult.Fail("Failed Auth"));
}
public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
{
_context = context;
return Task.CompletedTask;
}
}
现在,如果该原理没有Admin,则它将失败而没有错误,但是API返回的响应为200
,没有任何内容。我期待4xx
响应,并显示消息“身份验证失败”
我只是试图弄清为什么它看起来不像预期的那样“固定”,所以我不明白它是如何固定的。
我应该有更好的方法吗?
问候 标记
答案 0 :(得分:1)
为什么它看起来不像预期的那样“固定”,所以我不明白它是如何固定的。
当身份验证处理程序调用{{1}}方法时,没有黑魔法。我们必须自己做相关的事情。简而言之,根据需要设置IAuthenticationHandler.ForbidAsync()
。
StatusCode=403
请注意,您不必返回public async Task ForbidAsync(AuthenticationProperties properties)
{
properties = properties ?? new AuthenticationProperties();
_context.Response.StatusCode = 403;
// ...
return Task.CompletedTask;
}
,因为它并不关心结果。
我应该有更好的方法吗?
ASP.NET核心团队为我们提供了一个抽象类Task.FromResult()
来处理身份验证。此抽象类具有ForbidAsync(AuthenticationProperties properties)
(以及其他公共方法)的内置实现。因此,如下扩展该抽象类非常容易:
AuthenticationHandler
最后,添加身份验证服务的配置:
public class MyAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
public MyAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
return AuthenticateResult.NoResult();
}
}
它应该可以正常工作。