在dotnet核心3.1中使用IAuthorizationPolicyProvider的自定义实现进行身份验证



我已经按照这里提供的文档实现了一个自定义的IAuthorizationPolicyProvider,但当我调试并访问处理程序并查看上下文时。用户对象,我看到像IsAuthenticated或context这样的属性。User.IsInRole为false/空。我的应用程序配置了jwt令牌授权,我已经确认该令牌实际上包含角色负载数据中的值,但在到达处理程序以便我使用这些值之前,它似乎没有进行身份验证。有人能帮我理解操作顺序吗,或者我如何才能完成实际发生的身份验证?

我在Startup.cs:中同时拥有身份验证和授权

services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
services.AddAuthorization(options =>
{
var defaultAuthorizationBuilder = new AuthorizationPolicyBuilder("Bearer");
defaultAuthorizationBuilder = defaultAuthorizationBuilder.RequireAuthenticatedUser();
options.DefaultPolicy = defaultAuthorizationBuilder.Build();
}
services.AddSingleton<IAuthorizationPolicyProvider, MyCustomPolicyProvider>();
services.AddSingleton<IAuthorizationHandler, MyCustomHandler>();

经过多次修改,我想分享我所学到的答案,以及实现自定义策略提供程序如何工作的更广泛问题。在Startup.cs中使用AddAuthentication和AddAuthorization时,这将用作设置默认授权策略提供程序时使用的策略设置,例如:

public YourAuthorizationPolicyProvider(IOptions<AuthorizationOptions> options)
{
this.BackupPolicyProvider = new DefaultAuthorizationPolicyProvider(options);
}

对我来说,我使用这个后备策略提供程序作为默认值:

public Task<AuthorizationPolicy> GetDefaultPolicyAsync()
{
return this.BackupPolicyProvider.GetDefaultPolicyAsync(); //this is the default policy established in Startup.cs
}

(注意:我发现有些东西令人困惑,而且没有太多关于DefaultPolicy与FallbackPolicy的明确文档,特别是因为在撰写本文时,GetFallbackPolicyAsync最近成为了一种在实现IAuthorizationPolicyProvider时需要实现的方法。DefaultPolicy:当〔Authorize〕属性,这是要使用的策略。如果没有提供策略,则调用GetFallbackPolicyAsync。(

当我构建自定义策略时,我缺少的是在AuthorizationPolicyBuilder中指定我希望策略使用的身份验证方案。我现在意识到它在文档中,但它没有被特别调用,所以我错过了:

public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
{
if (//some check on your policy name)
{
var policy = new AuthorizationPolicyBuilder(//what scheme to use for authentication);
// your requirements
return Task.FromResult(policy.Build());
}
}

问题&目前的答案给了我很好的指导,告诉我如何自己配置它。共享如何配置自定义策略提供程序的完整示例。在我的情况下,我想用[AuthorizePermission("Read")]装饰操作,并由自定义AuthorizationHandler检查权限。

CustomPolicyProvider.cs

using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
namespace MyApp.Authentication.Policies
{
public class CustomPolicyProvider : IAuthorizationPolicyProvider
{
public DefaultAuthorizationPolicyProvider OriginalPolicyProvider { get; set; }
public CustomPolicyProvider(
IOptions<AuthorizationOptions> options)
{
OriginalPolicyProvider = new DefaultAuthorizationPolicyProvider(options);
}
public Task<AuthorizationPolicy> GetDefaultPolicyAsync() => OriginalPolicyProvider.GetDefaultPolicyAsync();
public Task<AuthorizationPolicy?> GetFallbackPolicyAsync() => OriginalPolicyProvider.GetFallbackPolicyAsync();
public Task<AuthorizationPolicy?> GetPolicyAsync(string policyName)
{
if (policyName.StartsWith(AuthSettings.Policies.Permission, StringComparison.OrdinalIgnoreCase))
{
var permission = policyName[AuthSettings.Policies.Permission.Length..];
if (!string.IsNullOrWhiteSpace(permission))
{
var policy = new AuthorizationPolicyBuilder(AuthSettings.Schemes.All);
policy.AddRequirements(new PermissionRequirement(permission));
return Task.FromResult<AuthorizationPolicy?>(policy.Build());
}
}
return OriginalPolicyProvider.GetPolicyAsync(policyName);
}
}
}

程序.cs

builder.Services.AddScoped<IAuthorizationHandler, PermissionAuthorizationHandler>();
builder.Services.AddAuthorization(options =>
{
options.DefaultPolicy =  new AuthorizationPolicyBuilder().RequireAuthenticatedUser()
.AddAuthenticationSchemes(AuthSettings.Schemes.All)
.Build();
options.AddPolicy(AuthSettings.Policies.Scopes.General, policy =>
{
policy.RequireAuthenticatedUser();
policy.AddAuthenticationSchemes(AuthSettings.Schemes.All);
policy.RequireScope("api");
});
options.AddPolicy(AuthSettings.Policies.Scopes.Identity, policy =>
{
policy.RequireAuthenticatedUser();
policy.AddAuthenticationSchemes(AuthSettings.Schemes.All);
policy.RequireScope("api.identity");
});
});
builder.Services.AddSingleton<IAuthorizationPolicyProvider, CustomPolicyProvider>();

最新更新