ASP.Net 5 AuthorizationHandler重定向失败

本文关键字:重定向 失败 AuthorizationHandler Net ASP | 更新日期: 2023-09-27 18:04:57

我试图添加一个自定义授权策略,可以检查json配置文件中提供的带分隔符的组列表。我用的是ASP。. Net 5 - MVC 6,以及windows认证。

一切都很好,除了当我调用Fail。然后什么也没发生。显示一个空白屏幕。这是我的handlerrequirementasync方法。我尝试了各种值的任务结果。我像个疯子一样在谷歌上搜索,但没有运气。希望有人能帮忙。

期望结果:我想重定向到一个自定义页面失败,但如果这是不可能的,至少能够重定向回登录页面。唯一有效的方法似乎是抛出异常。

Startup中的相关注册码:

var appSettings = Configuration.GetSection("AppSettings");
services.Configure<Models.AppSettings>(appSettings);
services.AddMvc();
services.AddAuthorization(options =>
{
    options.AddPolicy("RoleAuth", policy => policy.Requirements.Add(new RolesRequirement(appSettings["AllowedGroups"])));
});
services.AddSingleton<IAuthorizationHandler, RoleAuthorizationHandler>();

授权类:

public class RolesRequirement : IAuthorizationRequirement
{
    public RolesRequirement(string groups)
    {
        Groups = groups;
    }
    public string Groups { get; private set; }
}
public class RoleAuthorizationHandler : AuthorizationHandler<RolesRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RolesRequirement requirement)
    {
        if (!string.IsNullOrWhiteSpace(requirement.Groups))
        {
            Console.WriteLine(requirement.Groups);
            var groups = requirement.Groups.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            //we could check for group membership here.... maybe???
            foreach (var group in groups)
            {
                if (context.User.IsInRole(group))
                {
                    context.Succeed(requirement);
                    return Task.FromResult(0);
                }
            }
        }
        else
        {
            context.Succeed(requirement);
        }
        context.Fail();
        return Task.FromResult(0);
    }
}

ASP.Net 5 AuthorizationHandler重定向失败

我发现这样做的唯一方法是,不使用context.Fail(),而是这样做:

替换:

context.Fail();

:

var mvcContext = context.Resource as AuthorizationFilterContext;
mvcContext.Result = new RedirectToActionResult("Action", "Controller", null);
context.Succeed(requirement);

允许上下文成功,将执行上下文,现在是一个重定向。

我采用了herostwist的建议,但政策可以挑战或禁止。经过深入的研究,我发现是什么让您像这样直接访问AuthorizationFilterContext(因为它们遵循命名约定并继承自AuthorizeAttribute:

)
public class BudgetAccessFilterAttribute : AuthorizeAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        //context.HttpContext.User.Identity.Name
        //TODO: determine if user has access to budget controllers, all of them could inherit from a Common Controller with this Filter
        if (false)
        {
            //if no access then
            context.Result = new RedirectToActionResult("Index", "Home", null);
        }
    }     
}

你可以这样装饰你的控制器:

[BudgetAccessFilter]
public class BudgetItemController : Controller
{
}

如果你有很多具有相同检查的控制器,那么它们都可以从基类继承,并带有如下注释:

[BudgetAccessFilter]
public class BCommonController : Controller
{
}

然后清理控制器:

public class BudgetItemController : BCommonController
{
} 

在尝试herotwist的答案并看到它不再在。net Core (context.Resource as AuthorizationFilterContext总是返回NULL)中工作后,我想出了这个似乎在。net 5中工作得很好。虽然有点粗糙....我真的很想看看这个应该如何完成。这应该是可能的吧?

总之,是这样的:

    if (accessAllowed)
    {
        context.Succeed(requirement);
    }
    else
    {
        var mvcContext = (context.Resource as Microsoft.AspNetCore.Http.DefaultHttpContext);
        if (mvcContext != null)
        {
            mvcContext.Response.Redirect("/the-url-you-want-to-redirect-to");
        }           
    }

我使用cookie身份验证而不是windows,但在Startup.cs中的Configure方法中,我有以下一段代码,告诉它去哪里

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    LoginPath = "/account/login",
    AuthenticationScheme = "Cookies",
    AutomaticAuthenticate = true,
    AutomaticChallenge = true
});

我不知道在哪里可以配置重定向结果,但至少我能够创建这样一个"Account/AccessDenied "。Cshtml "文件,该文件将在失败情况下显示。"帐户"是我的类名,当失败发生时,浏览器被重定向到这个Url:(http://localhost:39339/Account/AccessDenied?ReturnUrl=%2Fapp%2Fequipments)

这是我的控制器代码(Web/AccountController.cs)以及。

public class AccountController : Controller
{
    public IActionResult AccessDenied()
    {
        return View();
    }
}