I have the following authentication handler:
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"));
}
}
Run Code Online (Sandbox Code Playgroud)
I register it like this in ConfigureServices:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CustomAuthenticationSchemeOptions.SchemeName;
options.DefaultChallengeScheme = CustomAuthenticationSchemeOptions.SchemeName;
})
.AddScheme<CustomAuthenticationSchemeOptions, CustomAuthenticationHandler>(CustomAuthenticationSchemeOptions.SchemeName, null);
Run Code Online (Sandbox Code Playgroud)
Then I use it like this in Configure:
app.UseAuthentication();
Run Code Online (Sandbox Code Playgroud)
I have several Controllers with several Actions. Some of those actions should be accessed only after authentication.
I thought that if I use the [Authorize] attribute, I make sure that only authenticated users can access it, so my middleware will be called with that request and the authentication protocol is executed (I guess it would be a very elegant and efficient solution).
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)
{
//...
}
}
Run Code Online (Sandbox Code Playgroud)
It seems that I was wrong, as each middleware is called each time when a request arrives.
So if I don't want to search the database after each Action request, I have to filter when the middleware is used.
I see some condition-based solution to use app.UseWhen and test the request path and other cumbersome ways.
Is there a more elegant and efficient way? As I have many actions, I can't create path checking for every one of them.
如果您将授权添加到您的中间件管道,这将是对您的 API 的所有调用的默认设置。因此,所有调用都将表现为[Authorize]应用了该属性。
这通常是可取的,因为这意味着默认情况下您的应用程序是安全的,并且您不会意外忘记 [Authorize] 属性。我建议保持这样,只需将[AllowAnonymous]标签添加到您想要公开的控制器或控制器操作。
如果您想始终明确,您只需删除app.UseAuthentication();您仍然可以使用[Authorize]它,因为您添加了要使用的服务,这将触发您的中间件。但它不会自动触发所有调用。
额外的:
为了使用授权而不必为每次调用指定方案,您可以将方案设置为默认授权策略。
services.AddAuthorization(options =>
{
var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(
CustomAuthenticationSchemeOptions.SchemeName);
defaultAuthorizationPolicyBuilder =
defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
});
Run Code Online (Sandbox Code Playgroud)
为了扩展其他人所说的内容,身份验证和授权之间存在细微差别。身份验证说明用户是谁,授权说明他们可以做什么。以上所有只是说...只要我知道用户是谁(已通过身份验证),他们就可以使用我的操作(已授权)。因此,如果用户成功通过身份验证,则您的默认授权策略是有效的。
| 归档时间: |
|
| 查看次数: |
8805 次 |
| 最近记录: |