InvalidOperationException:找不到策略

时间:2018-12-03 22:20:21

标签: c# asp.net-core authorization

我正在以dotnet核心构建网站,并且最近开始使用基于声明的身份验证和授权。

在视图组件中,我正在检查用户是否有权访问策略。

InvalidOperationException: No policy found: Admin.

但是,我收到异常startup.cs

我的ConfigureServicesservices.AddAuthorization(options => { options.AddPolicy("Admin", policy => policy.Requirements.Add(new HasPermissionRequirement("ADMIN"))); }); 方法中包含以下内容:

IAuthorizationHandler

我还需要配置什么才能使其正常工作?

作为参考,我正在注册3个另外的IAuthorizationPolicyProvider实现和1个public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { // Name and policy settings options.Cookie.Name = "account"; options.Cookie.SameSite = SameSiteMode.Strict; options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; options.Cookie.HttpOnly = true; // Sign the user out after 28 days of inactivity options.SlidingExpiration = true; options.ExpireTimeSpan = TimeSpan.FromDays(28); // Challenge actions options.LoginPath = new PathString("/account/login"); options.ReturnUrlParameter = "returnUrl"; }); services.AddAuthorization(options => { options.AddPolicy("Admin", policy => policy.Requirements.Add(new HasPermissionRequirement("ADMIN"))); }); services.AddSingleton<IAuthorizationHandler, HasPermissionHandler>(); services.AddSingleton<IAuthorizationHandler, StrategyAuthorizationCrudHandler>(); services.AddSingleton<IAuthorizationHandler, UserAuthorizationCrudHandler>(); services.AddSingleton<IAuthorizationPolicyProvider, HasPermissionPolicyProvider>(); // AddAntiforgery, AddSession,AddDistributedRedisCache and AddDataProtection omitted services.AddMvc() .SetCompatibilityVersion(CompatibilityVersion.Version_2_1) .AddJsonOptions(options => { options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); } app.UseCookiePolicy(new CookiePolicyOptions { CheckConsentNeeded = httpContext => false, MinimumSameSitePolicy = SameSiteMode.Strict, Secure = CookieSecurePolicy.SameAsRequest }); app.UseAuthentication(); app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto }); app.UseStaticFiles(); var supportedCultures = new[] { new CultureInfo("en-GB") }; app.UseRequestLocalization(new RequestLocalizationOptions { DefaultRequestCulture = new RequestCulture(supportedCultures[0]), SupportedCultures = supportedCultures, SupportedUICultures = supportedCultures }); app.UseSession(); app.UseMiddleware<UserMiddleware>(); app.UseMiddleware<LoggingMiddleware>(); app.UseMvc(routes => { routes.MapRoute( "default", "{controller=Home}/{action=Index}/{id?}"); }); }

修改

作为参考,整个startup.cs看起来与此有些

public class HasPermissionRequirement : IAuthorizationRequirement
{
    public string Permission { get; private set; }

    public HasPermissionRequirement(string permission)
    {
        Permission = permission;
    }
}

HasPermissionRequirement.cs

public class HasPermissionHandler : AuthorizationHandler<HasPermissionRequirement>
{
    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context,
        HasPermissionRequirement requirement)
    {
        var hasPermission = context.User.HasClaim("Permission", requirement.Permission);
        if (hasPermission)
            context.Succeed(requirement);

        return Task.CompletedTask;
    }
}

HasPermissionHandler.cs

public class HasPermissionPolicyProvider : IAuthorizationPolicyProvider
{
    private const string PolicyPrefix = "HasPermission";

    public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
    {
        if (!policyName.StartsWith(PolicyPrefix, StringComparison.OrdinalIgnoreCase))
            return Task.FromResult<AuthorizationPolicy>(null);

        var permission = policyName.Substring(PolicyPrefix.Length);

        var policy = new AuthorizationPolicyBuilder();
        policy.AddRequirements(new HasPermissionRequirement(permission));

        return Task.FromResult(policy.Build());
    }

    public Task<AuthorizationPolicy> GetDefaultPolicyAsync() => 
        Task.FromResult(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build());
}

HasPermissionPolicyProvider.cs

SimpleMessageListenerContainer

1 个答案:

答案 0 :(得分:0)

在设法指出正确的方向后,我已经通过仔细查看Microsoft文档来设法解决此问题。

https://github.com/aspnet/Docs/blob/master/aspnetcore/security/authorization/iauthorizationpolicyprovider.md#multiple-authorization-policy-providers

  

使用自定义IAuthorizationPolicyProvider实现时,请记住,ASP.NET Core仅使用IAuthorizationPolicyProvider的一个实例。如果自定义提供程序不能为所有策略名称提供授权策略,则应回退到备份提供程序。

结果,我将HasPermissionPolicyProvider的实现更改为CustomPolicyProvider,内容如下:

public class CustomPolicyProvider : DefaultAuthorizationPolicyProvider
{
    private const string PermissionPolicyPrefix = "HasPermission";

    public CustomPolicyProvider(IOptions<AuthorizationOptions> options) : base(options)
    {
    }

    public override async Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
    {
        var policy = await base.GetPolicyAsync(policyName);

        if (policy != null) return policy;

        if (policyName.StartsWith(PermissionPolicyPrefix, StringComparison.OrdinalIgnoreCase))
        {
            var permission = policyName.Substring(PermissionPolicyPrefix.Length);

            return new AuthorizationPolicyBuilder()
                .AddRequirements(new HasPermissionRequirement(permission))
                .Build();
        }

        return null;
    }
}

这意味着您只能拥有一个必须处理所有逻辑的PolicyProvider。更改是为了确保在您需要多个处理程序逻辑时调用默认实现。