我有以下身份验证处理程序:
public class CustomAuthenticationHandler : AuthenticationHandler<CustomAuthenticationSchemeOptions>
{
public CustomAuthenticationHandler (
IOptionsMonitor<CustomAuthenticationSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock) : base(options, logger, encoder, clock)
{
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
var data = await GetDataFromDatabase(); //heavy load
if(data.IsAuth)
{
var identity = new ClaimsIdentity(claims, Scheme.Name);
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, Scheme.Name);
return Task.FromResult(AuthenticateResult.Success(ticket));
}
return Task.FromResult(AuthenticateResult.Failed("Not authenticated"));
}
}
我在
ConfigureServices
中这样注册:services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CustomAuthenticationSchemeOptions.SchemeName;
options.DefaultChallengeScheme = CustomAuthenticationSchemeOptions.SchemeName;
})
.AddScheme<CustomAuthenticationSchemeOptions, CustomAuthenticationHandler>(CustomAuthenticationSchemeOptions.SchemeName, null);
然后我在
Configure
中这样使用它:app.UseAuthentication();
我有几个
Controllers
有几个 Actions
.其中一些操作应仅在身份验证后访问。我想如果我使用
[Authorize]
属性,我确保只有经过身份验证的用户才能访问它,所以我的中间件将使用该请求调用并执行身份验证协议(protocol)(我想这将是一个非常优雅和有效的解决方案)。public class RegisterController: ControllerBase
{
public async Task<AsyncResult<int>>> Reg(string name)
{
//...
}
}
[Authorize]
public class DataController: Controller
{
public async Task<AsyncResult<Data>>> GetData(int dataId)
{
//...
}
}
看来我错了,因为每个中间件都是called each time当请求到达时。
所以如果我不想在每个
Action
之后搜索数据库请求,我必须在使用中间件时进行过滤。我看到了一些基于条件的解决方案来使用
app.UseWhen
并测试请求路径等繁琐的方式。有没有更优雅高效的方法?由于我有很多 Action ,我无法为每个 Action 创建路径检查。
最佳答案
如果您将授权添加到中间件管道,这将是对您的 API 的所有调用的默认设置。因此,所有调用都将如同拥有 [Authorize]
应用的属性。
这通常是可取的,因为这意味着默认情况下您的应用程序是安全的,并且您不会意外忘记 [Authorize] 属性。我建议保持这样,只需添加 [AllowAnonymous]
标记到您想要公开的 Controller 或 Controller 操作。
如果你想在任何时候都明确,你只需删除 app.UseAuthentication();
您仍然可以使用 [Authorize]
当您添加服务以供使用时,这将触发您的中间件。但它不会自动触发所有调用。
补充:
为了使用授权而不必为每次调用指定方案,您可以将方案设置为默认授权策略。
services.AddAuthorization(options =>
{
var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(
CustomAuthenticationSchemeOptions.SchemeName);
defaultAuthorizationPolicyBuilder =
defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
});
为了扩展其他人所说的,身份验证和授权之间存在细微差别。身份验证说明用户是谁,授权说明允许他们做什么。以上只是说...只要我知道用户是谁(已验证),他们就可以使用我的操作(已授权)。因此,如果用户成功通过身份验证,您的默认授权策略是有效的。
关于c# - 在 ASP.NET Core 中不需要时如何绕过身份验证中间件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56524306/