AuthorizeFilter失败时如何返回403而不是重定向到拒绝访问

时间:2019-01-31 12:55:31

标签: c# asp.net-core asp.net-core-mvc asp.net-core-2.2

在Startup.ConfigureServices()中,我这样配置授权过滤器:

services.AddMvc(options =>
{
    options.Filters.Add(new AuthorizeFilter(myAuthorizationPolicy));
})

并且我基于配置使用cookie身份验证或AAD身份验证:

if (useCookieAuth)
{
    services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie();
}
else
{
    services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
       .AddAzureAD(options => Configuration.Bind("Authentication:AzureAd", options));
}

现在,当我访问页面并且myAuthorizationPolicy失败时,我被重定向到“ Account / AccessDenied?ReturnUrl =%2F”,但我想返回403。

5 个答案:

答案 0 :(得分:2)

对于那些使用 Azure AD 并在他们的 ConfigureServices 中使用的人(咳嗽我):

services.AddMicrosoftIdentityWebAppAuthentication(Configuration);

解决方案如下:

        services.Configure<CookieAuthenticationOptions>(CookieAuthenticationDefaults.AuthenticationScheme, options =>
        {
            options.Events.OnRedirectToAccessDenied = new Func<RedirectContext<CookieAuthenticationOptions>, Task>(context =>
            {
                context.Response.StatusCode = StatusCodes.Status403Forbidden;
                return context.Response.CompleteAsync();
            });
        });

这样,ASP.NET 将不再重定向到 AccessDenied,而是返回一个 403

可以在此处找到更多详细信息:https://blog.johnnyreilly.com/2020/12/how-to-make-azure-ad-403.html(但我希望您真正需要的只是这个答案)

答案 1 :(得分:1)

我最近遇到了这个问题,并且能够在以下位置找到与如何在AzureADB2C中覆盖默认cookie行为有关的说明:

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/azure-ad-b2c?view=aspnetcore-3.1#configure-the-underlying-openidconnectoptionsjwtbearercookie-options

以下是实现该覆盖以返回简单403而不是重定向的示例:

services
    .AddAuthentication(AzureADB2CDefaults.AuthenticationScheme)
    .AddAzureADB2C();

services.Configure<CookieAuthenticationOptions> (AzureADB2CDefaults.CookieScheme, options =>
{
    // Stop AzureADB2C from redirecting 403's, which it does by default.  We just want to return the 403.
    options.Events.OnRedirectToAccessDenied = new Func<RedirectContext<CookieAuthenticationOptions>, Task>(context =>
    {
        context.Response.StatusCode = StatusCodes.Status403Forbidden;
        return context.Response.CompleteAsync();
    });
});

希望这对某人有帮助。

答案 2 :(得分:0)

public class AuthorizeOrForbidAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            filterContext.Result = new HttpStatusCodeResult(403);
        }

    }
}

尝试上面的过滤器。

答案 3 :(得分:0)

似乎您必须重写OnRedirectToAccessDenied

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options => {
        options.Events.OnRedirectToAccessDenied = context => {
             context.Response.StatusCode = 403;
        };
    });

答案 4 :(得分:0)

您可以结合自己的政策创建自定义Authorization Filter

public class MyAuthorizeFilter: IAsyncAuthorizationFilter
{
    public MyAuthorizeFilter(string policy)
    {
        Policy = policy;
    }

    public string Policy { get; set; }
    public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
    {
        var user = context.HttpContext.User;

        var authZService = context.HttpContext.RequestServices.GetRequiredService<IAuthorizationService>();
        var accessable = await authZService.AuthorizeAsync(user, null, this.Policy);
        if (!accessable.Succeeded)
        {
            context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
        }

    }
}

现在您可以使用授权过滤器拦截请求:

[MyAuthorizeFilter("MyPolicy")]
public IActionResult Index()

或全局:

services.AddMvc(options =>
        {
            options.Filters.Add(new MyAuthorizeFilter("MyPolicy"));              
        });

当然,我们需要先注册该政策。

services.AddAuthorization(o => {
            o.AddPolicy("MyPolicy", pb => {
                pb.RequireAuthenticatedUser();
                //...
            });
        });