AuthorizeFilter 失败时如何返回 403 而不是重定向访问被拒绝
Posted
技术标签:
【中文标题】AuthorizeFilter 失败时如何返回 403 而不是重定向访问被拒绝【英文标题】:How to return 403 instead of redirect to access denied when AuthorizeFilter fails 【发布时间】: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。
【问题讨论】:
【参考方案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您可以结合您的策略创建自定义 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 登录页面。关于它可能是什么的任何线索?以上是关于AuthorizeFilter 失败时如何返回 403 而不是重定向访问被拒绝的主要内容,如果未能解决你的问题,请参考以下文章
请求正常时如何返回json对象,SpringBoot失败时如何返回json错误对象
如何设置 SBT 构建以在 Jenkins 测试失败时返回零退出代码?
在clickhouse中,投射失败时如何返回null而不是抛出异常?