Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirect Unauthorized Page Access in MVC to Custom View

Tags:

I have an MVC website in which access is based on various Roles. Once a user logs into the system they can see navigation to the pages for which they are authorized. However, some users may still try to access pages using a direct URL. If they do, the system automatically redirects them to the Login Page. Instead of the Login Page I want to redirect them to another view (Unauthorized).

Web.Config has the following entry:

    <customErrors mode="On">       <error statusCode="401" redirect="~/Home/Unauthorized" />       <error statusCode="404" redirect="~/Home/PageNotFound" />     </customErrors>     <authentication mode="Forms"> <forms name="Development" loginUrl="~/Account/Login" cookieless="UseCookies" timeout="120"></forms>     </authentication> 

I have registered these routes in Global.asax.cs as well.

routes.MapRoute(     name: "Unauthorized",     url: "{controller}/{action}/{id}",     defaults: new { controller = "Home", action = "Unauthorized", id = UrlParameter.Optional }    );   routes.MapRoute(     name: "PageNotFound",     url: "{controller}/{action}/{id}",     defaults: new { controller = "Home", action = "PageNotFound", id = UrlParameter.Optional }     ); 

Will it be enough?

like image 332
user2739418 Avatar asked Feb 27 '14 16:02

user2739418


People also ask

How redirect to action in view in MVC?

You can use the RedirectToAction() method, then the action you redirect to can return a View. The easiest way to do this is: return RedirectToAction("Index", model); Then in your Index method, return the view you want.

How do you restrict access to action in MVC?

To restrict the public action method in MVC, we can use the “NonAction” attribute. The “NonAction” attribute exists in the “System. Web.


2 Answers

After some research I think the easiest answer to this problem is just creating custom authorize, very similar to the one by jbbi (but that one didn't work since the "new HttpUnauthorizedResult()" is internaly automatically redirecting to the login - at least in mvc 5 with identity)

public class CustomAuthorize : AuthorizeAttribute {     protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)     {         if (!filterContext.HttpContext.User.Identity.IsAuthenticated)         {             //if not logged, it will work as normal Authorize and redirect to the Login             base.HandleUnauthorizedRequest(filterContext);          }         else         {             //logged and wihout the role to access it - redirect to the custom controller action             filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Error", action = "AccessDenied" }));         }     } } 

and the usage is the same as the default Authorize:

[CustomAuthorize(Roles = "Administrator")] 

Then, just to do things right, don't forget to send out the Http code of the error page. e.g like this in the controller.

public ActionResult AccessDenied() {     Response.StatusCode = 403;     return View(); } 

It's easy, it works and even I (a .net mvc rookie) understand this.

Note: It doesn't work the same with a 401 code - it will always take over the 401 and internaly redirect it to the login. But in my case is, by definition, the 403 also fitting.

like image 140
The Vojtisek Avatar answered Sep 28 '22 10:09

The Vojtisek


With following change it is working

public class CustomAuthorize : AuthorizeAttribute {     protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)     {         //filterContext.Result = new HttpUnauthorizedResult(); // Try this but i'm not sure           filterContext.Result = new RedirectResult("~/Home/Unauthorized");     }      public override void OnAuthorization(AuthorizationContext filterContext)     {         if (this.AuthorizeCore(filterContext.HttpContext))         {             base.OnAuthorization(filterContext);         }         else         {             this.HandleUnauthorizedRequest(filterContext);         }     }  } 

And then applying on Controller or Action as below:

[CustomAuthorize(Roles = "Admin")] 

With above approach I need to revisit all the controller/actions and change the Authorized attribute! Also some testing will be needed.

I am still not sure why Web.Config route not working as same has been explained in MVC Documentation. May be something has changed in MVC 4!

like image 38
user2739418 Avatar answered Sep 28 '22 09:09

user2739418