How to force the Authorize attribute to return a custom 403 error page instead of redirecting to the login page

[Authorize] Attribute is a nice and convenient invention of MS, and I hope that he can solve the problems that I have now.

More specific:

When the current client is not authenticated - [Authorize] redirects from the protected action to the login page and after successful login - returns the user, this is good.

But when the current client is already authenticated but not authorized to start a specific action - all I need to do is just show my 403 shared page.

Is this possible without moving the authorization logic into the body of the controller?

Update : The behavior I need should be semantically equal to this sketch:

 public ActionResult DoWork() { if (!NotAuthorized()) { // this should be not redirect, but forwarding return RedirectToAction("403"); } return View(); } 

so - there should be no redirects and URLs that should remain unchanged, but the page content should be replaced with 403 pages

Update 2 . I implemented the sketch as follows:

 [HandleError] public class HomeController : Controller { public ActionResult Index() { ViewData["Message"] = "Welcome to ASP.NET MVC!"; return View(); } [CustomActionFilter] public ActionResult About() { return View(); } public ActionResult Error_403() { return Content("403"); } } public class CustomActionFilter : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { filterContext.Result = new ContentResult { Content = "403" }; } } 

And it doesn’t work out how to redirect execution correctly to HomeController.Action_403 () so that it displays 403.

Update 3 :

 filterContext.Result = new ViewResult() { ViewName = "Error_403" }; 

so this is the answer to how to render a certain presentation template ... but still don’t know how to start another controller - in any case, this is a pretty good solution.

+43
security c # authorization asp.net-mvc
Apr 05 2018-10-14T00:
source share
2 answers

You should be able to create your own class that derives from AuthorizeAttribute and override AuthorizeCore to provide the authorization mechanism that you want so that you can apply your own authorization code using the attribute instead of moving it to the controller.

If you require more granular control over authorization, I recommend that you create an implementation of the IActionFilter interface (per attribute, then apply the attribute to your methods). This will allow you to intercept calls before they go to the controller, and provide alternative actions before calling the controller method.

This is achieved by implementing the OnActionExecuting method in the IActionFilter interface. If your logic determines that you should not call the controller at all, and you want to process the ActionResult instead, then you set the Result property to the ActionExecutingContext passed to the method. By doing this, the ActionResult processed instead of going to the controller method to get the ActionResult .

If you want to return error code 403, you cannot use the ContentResult class. You will need to create your own class derived from ActionResult and override the ExecuteResult method to set the StatusCode property to HttpResponseBase to 403, for example:

 internal class Http403Result : ActionResult { public override void ExecuteResult(ControllerContext context) { // Set the response code to 403. context.HttpContext.Response.StatusCode = 403; } } public class CustomActionFilter : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { filterContext.Result = new Http403Result(); } } 

Of course, you can generalize the Http403Result class to take a constructor that accepts the status code you want to return, but the concept remains the same.

+29
Apr 05 '10 at 14:11
source share

What I would do is subclass AuthorizeAttribute and override it with HandleUnauthorizedRequest to return an HTTP 403 status code if the user authenticated. Then I will add the system.webServer \ httpErrors section to my Web.Config to replace the standard 403 with my user page (IIS 7+ is required for this last part). Here's how:

 public class MyAuthorizeAttribute : AuthorizeAttribute { protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { if (filterContext.HttpContext.User.Identity.IsAuthenticated) filterContext.Result = new HttpStatusCodeResult(403); else filterContext.Result = new HttpUnauthorizedResult(); } } <configuration> <system.webServer> <httpErrors errorMode="Custom" existingResponse="Replace"> <remove statusCode="403" /> <error statusCode="403" responseMode="ExecuteURL" path="/Error/MyCustom403page" /> </httpErrors> </system.webServer> </configuration> 
+46
Jun 21 2018-11-21T00:
source share



All Articles