【问题标题】:How to return 403 instead of redirect to access denied when AuthorizeFilter failsAuthorizeFilter 失败时如何返回 403 而不是重定向访问被拒绝
【发布时间】:2019-06-24 22:42:36
【问题描述】:

在 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。

【问题讨论】:

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


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

    试试上面的过滤器。

    【讨论】:

    • 我应该在哪里使用这个?
    • options.Filters.Add(new AuthorizeFilter(myAuthorizationPolicy));你可以发送 myAuthorizationPolicy 方法吗?我得先看看这个方法。
    • 如果 myAuthorizationPolicy 方法中没有任何代码,请创建一个类似上述代码的类。并删除您的代码 options.Filters.Add(new AuthorizeFilter(myAuthorizationPolicy));
      .然后添加这一行 options.Filters.Add(new AuthorizeOrForbidAttribute());
    【解决方案2】:

    看来你必须重写 OnRedirectToAccessDenied

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

    【讨论】:

    • 是的,但是 AAD 身份验证呢?
    • 更有可能您必须创建自己的 AddAzureAD(),因为它似乎还无法配置......
    • 类似于 public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder, Action configureOptions) { builder.Services.Configure(configureOptions); builder.Services.AddSingleton, ConfigureAzureOptions>(); builder.AddOpenIdConnect(options => { options.Events = new OpenIdConnectEvents { OnRedirectToIdentityProvider = RedirectToIdentityProvider }; });返回建设者; }
    • 效果不错!!它缺少返回 Task.CompletedTask
    • @BorisSokolov:当然可以。我做到了:stackoverflow.com/questions/63191785/…
    【解决方案3】:

    您可以结合您的策略创建自定义 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();
                    //...
                });
            });
    

    【讨论】:

      【解决方案4】:

      我最近遇到了这个问题,并且能够在以下位置找到有关如何覆盖 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();
          });
      });
      

      希望这对某人有所帮助。

      【讨论】:

        【解决方案5】:

        对于那些使用 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/21/how-to-make-azure-ad-403/(但我希望你真正需要的只是这个答案)

        【讨论】:

        • 我试过这个,但由于某种原因它不起作用(函数中的断点没有被触发)。我仍然被重定向到 ADB2C 登录页面。关于它可能是什么的任何线索?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-11-06
        • 2018-04-23
        • 1970-01-01
        • 2012-05-31
        • 2015-09-07
        • 2022-01-16
        • 2022-06-14
        相关资源
        最近更新 更多