简体   繁体   中英

How to show Access Denied instead of redirecting to login page?

I'm using ASP.NET Identity 2 in an ASP.NET MVC 5 application with OWIN. As of now, if an authenticated user tries to access an action he does not have a role for, he's redirected to the login page. How can I make it so authenticated users get an AccessDenied page in that case, but unauthenticated users still get sent to login page?

ConfigureAuth method as follows:

public void ConfigureAuth(IAppBuilder app)
{
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/Account/Login"),
        Provider = new CookieAuthenticationProvider
        {
        }
    });
    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
    app.UseSaml2Authentication(GetSamlOptions());
}

Try this custom authorize attribute, it does not redirect but replace the content instead so the url is intact, and also supports ajax request:

    public class AppAuthorizeAttribute : AuthorizeAttribute
    {

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            var isAuthorized = base.AuthorizeCore(httpContext);
            if (!isAuthorized)
            {
                return false;
            }
            // do another checks here...
        }

        // This will be executed when AuthorizeCore returns false
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.User.Identity.IsAuthenticated)
            {
                if (filterContext.HttpContext.Request.IsAjaxRequest())
                {
                    var urlHelper = new UrlHelper(filterContext.RequestContext);
                    filterContext.HttpContext.Response.StatusCode = 403;
                    filterContext.Result = new JsonResult
                    {
                        Data = new
                        {
                            ErrorMessage = "Unauthorized"
                        },
                        JsonRequestBehavior = JsonRequestBehavior.AllowGet
                    };
                }
                else
                {
                    filterContext.Result = new ViewResult
                    {
                        ViewName = "~/Views/Error/AccessDenied.cshtml"
                    };
                }
            }
            else
            {
                base.HandleUnauthorizedRequest(filterContext);
            }
        }

    }

Replace all [Authorize] with your custom attribute [AppAuthorize]

You can use custom [DataAnnotations] based on roles to give access to certain users. Something like:


[OnlyAllowedAttribute("Roles=Admin")]
public IActionResult OnlyAuthenticatedUsers()
{
  return View();
}

public class OnlyAllowedAttribute: AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);

        if(Threading.Thread.CurrentPrincipal.Identity.IsAuthenticated)
        {
          if(filterContext.Result is HttpUnauthorizedResult)
          {
              filterContext.Result = new RedirectResult("~/Account/AcessDenied");
          }
        }
        else
        {
          filterContext.Result = new RedirectResult("~/Account/Login");
        }
    }
}

https://stackoverflow.com/a/1279854/9936356

I implemented a custom authorization attribute as follows:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public sealed class CustomAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);
        if (filterContext.Result is HttpUnauthorizedResult)
        {
            var route_values = new RouteValueDictionary
            {
                ["controller"] = "Account"
            };
            if (filterContext.HttpContext.User.Identity.IsAuthenticated)
            {
                route_values["action"] = "AccessDenied";
            }
            else
            {
                route_values["action"] = "Login";
                route_values["returnUrl"] = filterContext.HttpContext.Request.Url.PathAndQuery;
            }
            filterContext.Result = new RedirectToRouteResult(route_values);
        }
    }
}

I'm still open to any answer that leverages some OWIN configuration value.

Thanks to everyone that helped.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM