未指定authenticationScheme,并且使用基于自定义策略的授权未找到DefaultForbidScheme

Den*_*sel 5 c# authorization asp.net-core asp.net-core-2.0

我有如下定义的基于自定义策略的授权处理程序。身份验证是在用户点击此应用程序之前进行的,因此我只需要授权。我收到错误消息:

没有指定authenticationScheme,也没有DefaultForbidScheme。

如果授权检查成功,那么我不会收到错误,一切都很好。仅当授权检查失败时,才会发生此错误。我希望失败时返回401。

public class EasRequirement : IAuthorizationRequirement
{
    public EasRequirement(string easBaseAddress, string applicationName, bool bypassAuthorization)
    {
        _client = GetConfiguredClient(easBaseAddress);
        _applicationName = applicationName;
        _bypassAuthorization = bypassAuthorization;
    }

    public async Task<bool> IsAuthorized(ActionContext actionContext)
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)
public class EasHandler : AuthorizationHandler<EasRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, EasRequirement requirement)
    {
        var mvcContext = context.Resource as ActionContext;

        bool isAuthorized;

        try
        {
            isAuthorized = requirement.IsAuthorized(mvcContext).Result;
        }
        catch (Exception)
        {
            // TODO: log the error?
            isAuthorized = false;
        }

        if (isAuthorized)
        {
            context.Succeed(requirement);
            return Task.CompletedTask;
        }

        context.Fail();
        return Task.FromResult(0);
    }
}
Run Code Online (Sandbox Code Playgroud)
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        var easBaseAddress = Configuration.GetSection("EasBaseAddress").Value;
        var applicationName = Configuration.GetSection("ApplicationName").Value;
        var bypassAuthorization = bool.Parse(Configuration.GetSection("BypassEasAuthorization").Value);

        var policy = new AuthorizationPolicyBuilder()
            .AddRequirements(new EasRequirement(easBaseAddress, applicationName, bypassAuthorization))
            .Build();

        services.AddAuthorization(options =>
        {
            options.AddPolicy("EAS", policy);
        });

        services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        services.AddSingleton<IAuthorizationHandler, EasHandler>();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseAuthentication();

        app.UseMvc();
    }
}
Run Code Online (Sandbox Code Playgroud)

pok*_*oke 8

授权和身份验证在ASP.NET Core中紧密相连。当授权失败时,它将被传递给身份验证处理程序以处理授权失败。

因此,即使您不需要实际的身份验证来标识您的用户,您仍将需要设置一些身份验证方案,以处理禁止和挑战结果(403和401)。

为此,您需要调用AddAuthentication()并配置默认的禁止/挑战方案:

services.AddAuthentication(options =>
{
    options.DefaultChallengeScheme = "scheme name";

    // you can also skip this to make the challenge scheme handle the forbid as well
    options.DefaultForbidScheme = "scheme name";

    // of course you also need to register that scheme, e.g. using
    options.AddScheme<MySchemeHandler>("scheme name", "scheme display name");
});
Run Code Online (Sandbox Code Playgroud)

MySchemeHandler需要实施IAuthenticationHandler,在您的情况下,您尤其需要实施ChallengeAsyncForbidAsync

public class MySchemeHandler : IAuthenticationHandler
{
    private HttpContext _context;

    public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
    {
        _context = context;
        return Task.CompletedTask;
    }

    public Task<AuthenticateResult> AuthenticateAsync()
        => Task.FromResult(AuthenticateResult.NoResult());

    public Task ChallengeAsync(AuthenticationProperties properties)
    {
        // do something
    }

    public Task ForbidAsync(AuthenticationProperties properties)
    {
        // do something
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 如果有人想知道“做某事”应该是什么样子,请参阅 /sf/answers/3821093811/ (2认同)

Mar*_*sky 8

对于 IIS/IIS Express,只需在已接受的答案中添加此行而不是以上所有内容,即可获得您期望的相应 403 响应;

 services.AddAuthentication(IISDefaults.AuthenticationScheme);
Run Code Online (Sandbox Code Playgroud)