ASP.NET MVC redirect to an access denied page using a custom role provider

后端 未结 9 1968
忘了有多久
忘了有多久 2020-12-12 11:20

I\'m creating a custom role provider and I set a Authorize attribute specifying a role in my controller and it\'s working just fine, like this:

[Authorize(Ro         


        
相关标签:
9条回答
  • 2020-12-12 11:37
    [AccessDeniedAuthorize(Roles="SuperAdmin")]
    public class SuperAdminController : Controller
    

    AccessDeniedAuthorizeAttribute.cs:

    public class AccessDeniedAuthorizeAttribute : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);
    
            if(filterContext.Result is HttpUnauthorizedResult)
            {
                filterContext.Result = new RedirectResult("~/AcessDenied.aspx");
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-12 11:39

    A slight improvement to Matt's answer by avoiding the need to hard-code the Logon page and optionally setting the access denied view within the attribute:

    public class AccessDeniedAuthorizeAttribute : AuthorizeAttribute
    {
        public string AccessDeniedViewName { get; set; }
    
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);
    
            if (filterContext.HttpContext.User.Identity.IsAuthenticated &&
                filterContext.Result is HttpUnauthorizedResult)
            {
                if (string.IsNullOrWhiteSpace(AccessDeniedViewName))
                    AccessDeniedViewName = "~/Account/AccessDenied";
    
                filterContext.Result = new RedirectResult(AccessDeniedViewName);
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-12 11:42

    Redirect is not always the best solution

    Use standard http code 403:

    return new HttpStatusCodeResult(HttpStatusCode.Forbidden);
    
    0 讨论(0)
  • 2020-12-12 11:49

    I had similar issue. No matter what role I had, I was always redirected to LogIn page instead of AccessDenied. The fix was unbelievably easy, but it might not work in all cases. So it turned out, that I had wrong order in Startup.cs of these two lines:

    app.UseAuthentication();
    app.UseAuthorization();
    

    Make sure if app.UseAuthentication(); is BEFORE app.UseAuthorization();

    In other words, ask "Who are you?" first, and then "Are you allowed here?", not the other way.

    0 讨论(0)
  • 2020-12-12 11:53

    Here's my solution, based on eu-ge-ne's answer. Mine correctly redirects the user to the Login page if they are not logged in, but to an Access Denied page if they are logged in but are unauthorized to view that page.

    [AccessDeniedAuthorize(Roles="SuperAdmin")]
    public class SuperAdminController : Controller
    

    AccessDeniedAuthorizeAttribute.cs:

    public class AccessDeniedAuthorizeAttribute : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);
            if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
            {
                filterContext.Result = new RedirectResult("~/Account/Logon");
                return;
            }
    
            if (filterContext.Result is HttpUnauthorizedResult)
            {
                filterContext.Result = new RedirectResult("~/Account/Denied");
            }
        }
    }
    

    AccountController.cs:

    public ActionResult Denied()
    {
        return View();
    }
    

    Views/Account/Denied.cshtml: (Razor syntax)

    @{
        ViewBag.Title = "Access Denied";
    }
    
    <h2>@ViewBag.Title</h2>
    
    Sorry, but you don't have access to that page.
    
    0 讨论(0)
  • 2020-12-12 11:58

    I've built on Vic's answer to allow me to have a different Access Denied page for each of the application's areas. Did it by returning a RedirectToRouteResult instead, which instead of redirecting to a URL relative to the root of the application it redirects to the current area's controller and action:

    public class AccessDeniedAuthorizeAttribute : AuthorizeAttribute
    {
        public string AccessDeniedController { get; set; }
        public string AccessDeniedAction { get; set; }
    
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);
    
            if (filterContext.HttpContext.User.Identity.IsAuthenticated &&
                filterContext.Result is HttpUnauthorizedResult)
            {
                if (String.IsNullOrWhiteSpace(AccessDeniedController) || String.IsNullOrWhiteSpace(AccessDeniedAction))
                {
                    AccessDeniedController = "Home";
                    AccessDeniedAction = "AccessDenied";
                }
    
                filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { Controller = AccessDeniedController, Action = AccessDeniedAction }));
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题